diff --git a/fix_file_permissions.patch b/fix_file_permissions.patch index 3ad2009..78891ed 100644 --- a/fix_file_permissions.patch +++ b/fix_file_permissions.patch @@ -1,8 +1,8 @@ -Index: ipmitool-1.8.15/lib/helper.c +Index: ipmitool-1.8.16/lib/helper.c =================================================================== ---- ipmitool-1.8.15.orig/lib/helper.c 2015-01-14 14:28:25.104693872 +0100 -+++ ipmitool-1.8.15/lib/helper.c 2015-01-14 14:28:30.392693957 +0100 -@@ -659,7 +659,6 @@ +--- ipmitool-1.8.16.orig/lib/helper.c 2015-11-22 13:50:54.000000000 +0100 ++++ ipmitool-1.8.16/lib/helper.c 2016-02-25 13:25:40.147488838 +0100 +@@ -659,7 +659,6 @@ ipmi_start_daemon(struct ipmi_intf *intf #endif chdir("/"); @@ -10,11 +10,11 @@ Index: ipmitool-1.8.15/lib/helper.c for (fd=0; fd<64; fd++) { if (fd != intf->fd) -Index: ipmitool-1.8.15/src/ipmievd.c +Index: ipmitool-1.8.16/src/ipmievd.c =================================================================== ---- ipmitool-1.8.15.orig/src/ipmievd.c 2015-01-14 14:28:25.112693873 +0100 -+++ ipmitool-1.8.15/src/ipmievd.c 2015-01-14 14:28:30.392693957 +0100 -@@ -701,6 +701,7 @@ +--- ipmitool-1.8.16.orig/src/ipmievd.c 2015-11-22 13:50:54.000000000 +0100 ++++ ipmitool-1.8.16/src/ipmievd.c 2016-02-25 13:25:40.155489280 +0100 +@@ -701,6 +701,7 @@ ipmievd_main(struct ipmi_event_intf * ei int i, rc; int daemon = 1; struct sigaction act; @@ -22,7 +22,7 @@ Index: ipmitool-1.8.15/src/ipmievd.c memset(pidfile, 0, 64); sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum); -@@ -762,8 +763,9 @@ +@@ -763,8 +764,9 @@ ipmievd_main(struct ipmi_event_intf * ei ipmi_start_daemon(eintf->intf); diff --git a/fwum_enhance_output.patch b/fwum_enhance_output.patch index 1b22e3a..4975916 100644 --- a/fwum_enhance_output.patch +++ b/fwum_enhance_output.patch @@ -1,8 +1,8 @@ -Index: ipmitool-1.8.15/lib/ipmi_fwum.c +Index: ipmitool-1.8.16/lib/ipmi_fwum.c =================================================================== ---- ipmitool-1.8.15.orig/lib/ipmi_fwum.c 2015-01-14 14:28:25.108693872 +0100 -+++ ipmitool-1.8.15/lib/ipmi_fwum.c 2015-01-14 14:28:27.080693904 +0100 -@@ -1099,12 +1099,14 @@ +--- ipmitool-1.8.16.orig/lib/ipmi_fwum.c 2015-11-22 13:50:54.000000000 +0100 ++++ ipmitool-1.8.16/lib/ipmi_fwum.c 2016-02-25 13:25:35.907249893 +0100 +@@ -1098,12 +1098,14 @@ ipmi_kfwum_checkfwcompat(tKFWUM_BoardInf int compatible = 0; if (boardInfo.iana != firmInfo.iana) { lprintf(LOG_ERR, @@ -19,7 +19,7 @@ Index: ipmitool-1.8.15/lib/ipmi_fwum.c compatible = (-1); } if (compatible != 0) { -@@ -1122,6 +1124,10 @@ +@@ -1121,6 +1123,10 @@ printf_kfwum_info(tKFWUM_BoardInfo board printf( "Target IANA number : %u\n", boardInfo.iana); printf( diff --git a/ipmitool-1.8.15.tar.bz2 b/ipmitool-1.8.15.tar.bz2 deleted file mode 100644 index 952adcb..0000000 --- a/ipmitool-1.8.15.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4acd2df5f8740fef5c032cebee0113ec4d3bbef04a6f4dbfaf7fcc7f3eb08c40 -size 747174 diff --git a/ipmitool-1.8.16.tar.bz2 b/ipmitool-1.8.16.tar.bz2 new file mode 100644 index 0000000..2567d87 --- /dev/null +++ b/ipmitool-1.8.16.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c972fbfa9e400ba96a55464be25557f0386a1d44d238ebe9757c2b9b6e8eff7 +size 461483 diff --git a/ipmitool-1_8_15_HEAD.patch b/ipmitool-1_8_15_HEAD.patch deleted file mode 100644 index de040e6..0000000 --- a/ipmitool-1_8_15_HEAD.patch +++ /dev/null @@ -1,14169 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index 6c5ccfb..c1d0992 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -26,14 +26,13 @@ AC_C_CONST - AC_C_INLINE - AC_C_BIGENDIAN - --AC_FUNC_MALLOC - AC_FUNC_SELECT_ARGTYPES - AC_FUNC_STRTOD - AC_CHECK_FUNCS([alarm gethostbyname getaddrinfo getifaddrs socket select]) - AC_CHECK_FUNCS([memmove memset strchr strdup strerror]) - AC_CHECK_FUNCS([getpassphrase]) - --CFLAGS="$CFLAGS -fno-strict-aliasing -Wreturn-type" -+CFLAGS="$CFLAGS -Wall -Wextra -std=c99 -pedantic -Wformat -Wformat-nonliteral" - - AM_PROG_LIBTOOL - LIBTOOL="$LIBTOOL --silent" -@@ -60,6 +59,7 @@ dnl - xenable_intf_bmc=no - xenable_intf_imb=yes - xenable_intf_open=yes -+xenable_intf_usb=yes - xenable_intf_lipmi=yes - #xenable_intf_serial=yes - xenable_intf_dummy=no -@@ -131,6 +131,24 @@ if test "x$xenable_all_options" = "xyes" || test "x$xenable_solaris_opt" = "xyes - AC_DEFINE(ENABLE_ALL_OPTIONS, [1], [Define to 1 to enable all command line options.]) - fi - -+dnl Determine anonymous union/structure support in GCC -+AC_TRY_COMPILE([ -+#include -+ ], [ -+ struct test { -+ union { -+ int a; -+ unsigned int b; -+ }; -+ } test; -+ -+ printf("a is %d", test.a); -+ ], ac_need_fms_extension=no, ac_need_fms_extension=yes) -+if test "x$ac_need_fms_extension" = "xyes"; then -+ CFLAGS="$CFLAGS -fms-extensions" -+ AC_SUBST(CFLAGS) -+fi -+ - dnl check for OpenSSL functionality - AC_ARG_ENABLE([internal-md5], - [AC_HELP_STRING([--enable-internal-md5], -@@ -180,6 +198,22 @@ if test "x$xenable_intf_lan" = "xyes"; then - IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la" - fi - -+dnl enable IPMI USB interface -+AC_ARG_ENABLE([intf-usb], -+ [AC_HELP_STRING([--enable-intf-usb], -+ [enable IPMI USB interface [default=yes]])], -+ [xenable_intf_usb=$enableval], -+ [xenable_intf_usb=yes]) -+if test "x$xenable_intf_usb" = "xstatic" || test "x$xenable_intf_usb" = "xplugin"; then -+ xenable_intf_usb=yes -+fi -+if test "x$xenable_intf_usb" = "xyes"; then -+ AC_DEFINE(IPMI_INTF_USB, [1], [Define to 1 to enable USB interface.]) -+ AC_SUBST(INTF_USB, [usb]) -+ AC_SUBST(INTF_USB_LIB, [libintf_usb.la]) -+ IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la" -+fi -+ - dnl enable IPMIv2.0 RMCP+ LAN interface - AC_ARG_ENABLE([intf-lanplus], - [AC_HELP_STRING([--enable-intf-lanplus], -@@ -621,6 +655,7 @@ AC_CONFIG_FILES([Makefile - src/plugins/free/Makefile - src/plugins/imb/Makefile - src/plugins/bmc/Makefile -+ src/plugins/usb/Makefile - src/plugins/lipmi/Makefile - src/plugins/serial/Makefile - src/plugins/dummy/Makefile]) -@@ -637,6 +672,7 @@ AC_MSG_RESULT([ open : $xenable_intf_open]) - AC_MSG_RESULT([ free : $xenable_intf_free]) - AC_MSG_RESULT([ imb : $xenable_intf_imb]) - AC_MSG_RESULT([ bmc : $xenable_intf_bmc]) -+AC_MSG_RESULT([ usb : $xenable_intf_usb]) - AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi]) - AC_MSG_RESULT([ serial : $xenable_intf_serial]) - AC_MSG_RESULT([ dummy : $xenable_intf_dummy]) -diff --git a/contrib/Makefile.am b/contrib/Makefile.am -index c067dcb..98cec70 100644 ---- a/contrib/Makefile.am -+++ b/contrib/Makefile.am -@@ -35,7 +35,7 @@ dist_pkgdata_DATA = oem_ibm_sel_map - EXTRA_DIST = README \ - bmclanconf ipmi.init.basic ipmi.init.redhat \ - exchange-bmc-os-info.init.redhat exchange-bmc-os-info.service.redhat \ -- exchange-bmc-os-info.sysconf \ -+ exchange-bmc-os-info.sysconf log_bmc.sh\ - ipmievd.init.redhat ipmievd.init.suse ipmievd.init.debian \ - collect_data.sh create_rrds.sh create_webpage_compact.sh create_webpage.sh \ - bmc-snmp-proxy bmc-snmp-proxy.service bmc-snmp-proxy.sysconf -diff --git a/contrib/log_bmc.sh b/contrib/log_bmc.sh -new file mode 100644 -index 0000000..c7bbb76 ---- /dev/null -+++ b/contrib/log_bmc.sh -@@ -0,0 +1,88 @@ -+#!/bin/sh -+############################################################################# -+# -+# log_bmc.sh: Add SEL entries to indicate OS Boot/Install status. -+# -+# version: 0.1 -+# -+# Authors: Charles Rose -+# Jordan Hargrave -+# -+# Description: Script to log OS boot/install status to the BMC. Primarily -+# meant for use in automated installs and start up scripts. -+# Will provide administrators with OS boot/install status in -+# BMC and aid with debugging. -+# -+# Example usage: -+# # ./log_bmc.sh inst_start -+# # ipmitool sel list -+# b | 05/07/2014 | 12:07:32 | OS Boot | Installation started -+# -+# See here for details: -+# https://fedoraproject.org/wiki/Features/AgentFreeManagement -+# -+############################################################################# -+IPMI_CMD="/usr/bin/ipmitool" -+ -+############################################################################# -+# SEL Event types from ipmi_sel.h -+OS_STOP="0x20" -+OS_BOOT="0x1f" -+# SEL Event data from ipmi_sel.h -+GRACEFUL_SHUTDOWN="0x03" # OS Stop/Shutdown: Installation started -+BOOT_COMPLETED="0x01" # OS Boot: Installation started -+INSTALL_STARTED="0x07" # OS Boot: Installation started -+INSTALL_COMPLETED="0x08" # OS Boot: Installation completed -+INSTALL_ABORTED="0x09" # OS Boot: Installation aborted -+INSTALL_FAILED="0x0a" # OS Boot: Installation failed -+ -+########################################################################## -+ -+# check for ipmi functionality. -+check_ipmi() -+{ -+ # ensures presence of ipmitool and /dev/ipmi* -+ ${IPMI_CMD} mc info > /dev/null 2>&1 -+ [ $? -ne 0 ] && RETVAL=2 -+} -+ -+# Write out the events to SEL -+ipmi_sel_add() -+{ -+ # Refer ipmitool(1) event for details on format. -+ printf "0x04 %s 0x00 0x6f %s 0x00 0x00" ${type} ${status} > \ -+ ${tmpfile} && \ -+ ${IPMI_CMD} sel add ${tmpfile} > /dev/null 2>&1 -+ [ $? -ne 0 ] && RETVAL=3 -+} -+ -+### Main -+# Most of the status is for this event type -+tmpfile=$(/usr/bin/mktemp) -+RETVAL=0 -+type=${OS_BOOT} -+ -+case ${1} in -+ os_shutdown) type=${OS_STOP}; status=${GRACEFUL_SHUTDOWN} ;; -+ os_boot) status=${BOOT_COMPLETED} ;; -+ inst_start) status=${INSTALL_STARTED} ;; -+ inst_complete) status=${INSTALL_COMPLETED} ;; -+ inst_abort) status=${INSTALL_ABORTED} ;; -+ inst_fail) status=${INSTALL_FAILED} ;; -+ *) RETVAL=1 ;; -+esac -+ -+[ ${RETVAL} -eq 0 ] && check_ipmi -+[ ${RETVAL} -eq 0 ] && ipmi_sel_add ${status} -+ -+case ${RETVAL} in -+ 0) ;; -+ 1) printf -- %s\\n "Usage: $0 " ;; -+ 2) printf -- %s\\n "failed to communicate with BMC." ;; -+ 3) printf -- %s\\n "error adding ipmi sel entry." ;; -+esac -+ -+[ -f ${tmpfile} ] && rm -f ${tmpfile} > /dev/null 2>&1 -+ -+exit ${RETVAL} -+### End -diff --git a/doc/ipmitool.1 b/doc/ipmitool.1 -index 2c20821..10ccb74 100644 ---- a/doc/ipmitool.1 -+++ b/doc/ipmitool.1 -@@ -291,6 +291,7 @@ Commands: - kontronoem Manage Kontron OEM Extensions - lan Configure LAN Channels - mc Management Controller status and global enables -+ nm Node Manager - pef Configure Platform Event Filtering (PEF) - picmg Run a PICMG/ATA extended command - power Shortcut to chassis power commands -@@ -1921,6 +1922,27 @@ ADMIN, issue the following command: - - > ipmitool \-I \fIinterface\fR lan set \fIchannel\fR cipher_privs uaXXXXXXXXXXXXX - -+.TP -+ -+\fIbad_pass_thresh\fP <\fBthresh_num\fR> <\fB1|0\fR> <\fBreset_interval\fR> <\fBlockout_interval\fR> -+.br -+ -+Sets the Bad Password Threshold. -+ -+<\fBthresh_num\fR> If non-zero, this value determines the number of sequential bad passwords -+that will be allowed to be entered for the identified user before the user is automatically -+disabled from access on the channel. -+ -+<\fB1|0\fR> 1 = generate a Session Audit sensor "Invalid password disable" event message. -+0 = do not generate an event message when the user is disabled. -+ -+<\fBreset_interval\fR> Attempt Count Reset Interval. The interval, in tens of seconds, for -+which the accumulated count of bad password attempts is retained before being automatically -+reset to zero. -+ -+<\fBlockout_interval\fR> User Lockout Interval. The interval, in tens of seconds, that the user -+will remain disabled after being disabled because the Bad Password Threshold number was reached. -+ - .RE - .TP - \fIalert\fP \fIprint\fP [<\fBchannel\fR>] [<\fBalert destination\fR>] -@@ -2382,6 +2404,272 @@ Clear valid bit on power up via power push button or wake event - .RE - .RE - .RE -+.TP -+\fInm\fP -+.RS -+.TP -+\fIalert\fP -+.RS -+.TP -+\fIclear dest\fP <\fBdest\fR> -+.br -+ -+Clear the Node Manager Alert lan destination. -+ -+.RE -+.RS -+.TP -+\fIget\fP -+.br -+Get the Node Manager Alert settings. -+ -+.RE -+.RS -+.TP -+\fIset chan\fP <\fBchan\fR> \fIdest\fP <\fBdest\fR> \fIstring\fP <\fBstring\fR> -+.br -+ -+Set the Node Manager alert channel, lan destination, and alert string number. -+ -+.RE -+.TP -+\fIcapability\fP -+.br -+ -+Obtain the Node Manager power control capabilities and ranges. -+ -+.TP -+\fIcontrol\fP -+.RS -+.TP -+\fIenable\fP|\fIdisable \fP -+.RS -+.TP -+\fIglobal\fP -+.br -+ -+Enable/disable all policies for all domains. -+.TP -+\fIper_domain\fP -+.br -+ -+Enable/disable all policies of the specified domain. -+.TP -+\fIper_policy\fP <0-7> -+.br -+ -+Enable/disable the policy for the specified domain/policy combination. -+.RE -+.RE -+.TP -+\fIdiscover\fP -+.br -+ -+Discover Node Manager presence as well as the Node Manager version, revision, and patch number. -+ -+.TP -+\fIpolicy\fP -+.RS -+.TP -+\fIadd\fP -+.RS -+.TP -+\fIpower\fP \fIpolicy_id\fP <0-7> [\fIcorrection\fP auto|soft|hard] \fItrig_lim\fP \fIstats\fP [\fIdomain\fP ] \fIenable\fP|\fIdisable\fP -+.br -+ -+Add a new power policy, or overwrite an existing policy. -+The \fIcorrection\fP parameter is the agressiveness of frequency limiting, default is auto. -+The \fItrig_lim\fP is the correction time limit and must be at least 6000 and not greater than 65535. -+The \fIstats\fP setting is the averaging period in seconds and ranges from 1-65535. -+If domain is not supplied a default of platform is used. -+ -+ -+.TP -+\fIinlet\fP \fIpolicy_id\fP <0-7> [\fIcorrection\fP auto|soft|hard] \fItrig_lim\fP \fIstats\fP [\fIdomain\fP ] \fIenable\fP|\fIdisable\fP -+.br -+ -+Add a new inlet temp policy, or overwrite an existing policy. -+The \fIcorrection\fP parameter is the agressiveness of frequency limiting, default is auto. -+The \fItrig_lim\fP is the correction time limit and must be at least 6000 and not greater than 65535. -+The \fIstats\fP setting is the averaging period in seconds and ranges from 1-65535. -+If domain is not supplied a default of platform is used. -+ -+ -+.RE -+.TP -+\fIget\fP \fIpolicy_id\fP <0-7> -+.br -+ -+Get a previously stored policy. -+.TP -+\fIlimiting\fP -+.br -+ -+Report policy number if any policy is limiting power. -+.TP -+\fIremove\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Remove a policy. If domain is not supplied a default of platform is used. -+.RE -+.TP -+\fIpower\fP \fImin\fP \fImax\fP [\fIdomain\fP ] -+.br -+ -+Configure Node Manager power minumum and maximum power draw limits. -+The \fImin\fP and \fImax\fP values must be in the range of 0-65535. -+If domain is not supplied a default of platform is used. -+ -+.RE -+.RS -+.TP -+\fIreset\fP -+.RS -+.TP -+\fIcomm\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager communication statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIglobal\fI -+.br -+ -+Reset Node Manager global statistics. -+ -+.TP -+\fImemory\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager memory throttling statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIper_policy\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager per policy statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIrequests\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager unhandled requests statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIresponse\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager response time statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIthrottling\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Reset Node Manager throttling statistics. -+If domain is not supplied a default of platform is used. -+ -+.RE -+.TP -+\fIstatistics\fP -+.RS -+.TP -+\fIcomm_fail\fP -+.br -+ -+Report Node Manager communication failure statistics. -+ -+.TP -+\fIcpu_throttling\fP -+.br -+ -+Report Node Manager cpu throttling statistics. -+ -+.TP -+\fImem_throttling\fP -+.br -+ -+Report Node Manager memory throttling statistics. -+ -+.TP -+\fIpolicy_power\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Report Node Manager per policy power statistics (policy must be a power limit type policy). -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIpolicy_temps\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Report Node Manager per policy temp statistics (policy must be an inlet temp limit policy). -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIpolicy_throt\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Report Node Manager per policy throttling statistics. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIrequests\fP -+.br -+ -+Report Node Manager unhandled requests statistics. -+ -+.TP -+\fIresponse\fP -+.br -+ -+Report Node Manager response time statistics. -+ -+.RE -+.TP -+\fIsuspend\fP -+.RS -+.TP -+\fIget\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Get Node Manager policy suspend periods. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIset\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Set Node Manager policy suspend periods. -+If domain is not supplied a default of platform is used. -+The and values must be in the range of 0-239, which is the number of minutes past midnight divided by 6. -+The value is the daily recurrence pattern. Bit 0 is repeat every Monday, bit 1 is repeat every Tuesday, on through bit 6 for Sunday. -+ -+.RE -+.TP -+\fIthreshold\fP -+.RS -+.TP -+\fIget\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] -+.br -+ -+Get Node Manager policy Alert Threshold settings. -+If domain is not supplied a default of platform is used. -+ -+.TP -+\fIset\fP \fIpolicy_id\fP <0-7> [\fIdomain\fP ] \fIthresh_array\fP -+.br -+ -+Set Node Manager policy Alert Threshold values. -+If domain is not supplied a default of platform is used. -+The \fIthresh_array\fP is 1, 2, or 3 integers that set three alert threshold settings. The setting type is a power or temperature value which must match the type of policy. -+ -+.RE -+.RE -+ - .TP - \fIpef\fP - .RS -diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am -index 925881e..5a9062c 100644 ---- a/include/ipmitool/Makefile.am -+++ b/include/ipmitool/Makefile.am -@@ -38,5 +38,5 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \ - ipmi_oem.h ipmi_sdradd.h ipmi_isol.h ipmi_sunoem.h ipmi_picmg.h \ - ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \ - ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \ -- ipmi_delloem.h ipmi_dcmi.h -+ ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h - -diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h -index b6ee7fa..b7ad628 100644 ---- a/include/ipmitool/helper.h -+++ b/include/ipmitool/helper.h -@@ -83,9 +83,12 @@ int str2ushort(const char * str, uint16_t * ushrt_ptr); - int str2char(const char * str, int8_t * chr_ptr); - int str2uchar(const char * str, uint8_t * uchr_ptr); - -+int eval_ccode(const int ccode); -+ - int is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr); - int is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr); - int is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr); -+int is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr); - - uint16_t str2val(const char * str, const struct valstr * vs); - void print_valstr(const struct valstr * vs, const char * title, int loglevel); -diff --git a/include/ipmitool/ipmi.h b/include/ipmitool/ipmi.h -index 1fd3e2a..beda0ad 100644 ---- a/include/ipmitool/ipmi.h -+++ b/include/ipmitool/ipmi.h -@@ -260,6 +260,7 @@ typedef enum IPMI_OEM { - IPMI_OEM_HITACHI_116 = 116, - IPMI_OEM_NEC = 119, - IPMI_OEM_TOSHIBA = 186, -+ IPMI_OEM_ERICSSON = 193, - IPMI_OEM_INTEL = 343, - IPMI_OEM_TATUNG = 373, - IPMI_OEM_HITACHI_399 = 399, -@@ -269,7 +270,9 @@ typedef enum IPMI_OEM { - IPMI_OEM_BROADCOM = 4413, - IPMI_OEM_MAGNUM = 5593, - IPMI_OEM_TYAN = 6653, -+ IPMI_OEM_QUANTA = 7244, - IPMI_OEM_NEWISYS = 9237, -+ IPMI_OEM_ADVANTECH = 10297, - IPMI_OEM_FUJITSU_SIEMENS = 10368, - IPMI_OEM_AVOCENT = 10418, - IPMI_OEM_PEPPERCON = 10437, -diff --git a/include/ipmitool/ipmi_channel.h b/include/ipmitool/ipmi_channel.h -index 7cbb9ad..89e4738 100644 ---- a/include/ipmitool/ipmi_channel.h -+++ b/include/ipmitool/ipmi_channel.h -@@ -40,6 +40,7 @@ - - - #define IPMI_GET_CHANNEL_AUTH_CAP 0x38 -+#define IPMI_SET_CHANNEL_ACCESS 0x40 - #define IPMI_GET_CHANNEL_ACCESS 0x41 - #define IPMI_GET_CHANNEL_INFO 0x42 - #define IPMI_SET_USER_ACCESS 0x43 -@@ -49,6 +50,32 @@ - #define IPMI_SET_USER_PASSWORD 0x47 - #define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54 - -+/* These are for channel_info_t.session_support */ -+#define IPMI_CHANNEL_SESSION_LESS 0x00 -+#define IPMI_CHANNEL_SESSION_SINGLE 0x40 -+#define IPMI_CHANNEL_SESSION_MULTI 0x80 -+#define IPMI_CHANNEL_SESSION_BASED 0xC0 -+ -+/* (22.24) Get Channel Info */ -+struct channel_info_t { -+ uint8_t channel; -+ uint8_t medium; -+ uint8_t protocol; -+ uint8_t session_support; -+ uint8_t active_sessions; -+ uint8_t vendor_id[3]; -+ uint8_t aux_info[2]; -+}; -+ -+/* (22.23) Get Channel Access */ -+struct channel_access_t { -+ uint8_t access_mode; -+ uint8_t alerting; -+ uint8_t channel; -+ uint8_t per_message_auth; -+ uint8_t privilege_limit; -+ uint8_t user_level_auth; -+}; - - /* - * The Get Authentication Capabilities response structure -@@ -101,153 +128,12 @@ struct get_channel_auth_cap_rsp { - #pragma pack(0) - #endif - -- -- --/* -- * The Get Channel Info response structure -- * From table 22-29 of the IPMI v2.0 spec -- */ --#ifdef HAVE_PRAGMA_PACK --#pragma pack(1) --#endif --struct get_channel_info_rsp { --#if WORDS_BIGENDIAN -- uint8_t __reserved1 : 4; -- uint8_t channel_number : 4; /* channel number */ --#else -- uint8_t channel_number : 4; /* channel number */ -- uint8_t __reserved1 : 4; --#endif --#if WORDS_BIGENDIAN -- uint8_t __reserved2 : 1; -- uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */ --#else -- uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */ -- uint8_t __reserved2 : 1; --#endif --#if WORDS_BIGENDIAN -- uint8_t __reserved3 : 3; -- uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */ --#else -- uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */ -- uint8_t __reserved3 : 3; --#endif --#if WORDS_BIGENDIAN -- uint8_t session_support : 2; /* Description of session support */ -- uint8_t active_sessions : 6; /* Count of active sessions */ --#else -- uint8_t active_sessions : 6; /* Count of active sessions */ -- uint8_t session_support : 2; /* Description of session support */ --#endif -- uint8_t vendor_id[3]; /* For OEM that specified the protocol */ -- uint8_t aux_info[2]; /* Not used*/ --} ATTRIBUTE_PACKING; --#ifdef HAVE_PRAGMA_PACK --#pragma pack(0) --#endif -- -- -- --/* -- * The Get Channel Access response structure -- * From table 22-28 of the IPMI v2.0 spec -- */ --#ifdef HAVE_PRAGMA_PACK --#pragma pack(1) --#endif --struct get_channel_access_rsp { --#if WORDS_BIGENDIAN -- uint8_t __reserved1 : 2; -- uint8_t alerting : 1; -- uint8_t per_message_auth : 1; -- uint8_t user_level_auth : 1; -- uint8_t access_mode : 3; --#else -- uint8_t access_mode : 3; -- uint8_t user_level_auth : 1; -- uint8_t per_message_auth : 1; -- uint8_t alerting : 1; -- uint8_t __reserved1 : 2; --#endif --#if WORDS_BIGENDIAN -- uint8_t __reserved2 : 4; -- uint8_t channel_priv_limit : 4; /* Channel privilege level limit */ --#else -- uint8_t channel_priv_limit : 4; /* Channel privilege level limit */ -- uint8_t __reserved2 : 4; --#endif --} ATTRIBUTE_PACKING; --#ifdef HAVE_PRAGMA_PACK --#pragma pack(0) --#endif -- --#ifdef HAVE_PRAGMA_PACK --#pragma pack(1) --#endif --struct get_user_access_rsp { --#if WORDS_BIGENDIAN -- uint8_t __reserved1 : 2; -- uint8_t max_user_ids : 6; -- uint8_t __reserved2 : 2; -- uint8_t enabled_user_ids : 6; -- uint8_t __reserved3 : 2; -- uint8_t fixed_user_ids : 6; -- uint8_t __reserved4 : 1; -- uint8_t callin_callback : 1; -- uint8_t link_auth : 1; -- uint8_t ipmi_messaging : 1; -- uint8_t privilege_limit : 4; --#else -- uint8_t max_user_ids : 6; -- uint8_t __reserved1 : 2; -- uint8_t enabled_user_ids : 6; -- uint8_t __reserved2 : 2; -- uint8_t fixed_user_ids : 6; -- uint8_t __reserved3 : 2; -- uint8_t privilege_limit : 4; -- uint8_t ipmi_messaging : 1; -- uint8_t link_auth : 1; -- uint8_t callin_callback : 1; -- uint8_t __reserved4 : 1; --#endif --} ATTRIBUTE_PACKING; --#ifdef HAVE_PRAGMA_PACK --#pragma pack(0) --#endif -- --#ifdef HAVE_PRAGMA_PACK --#pragma pack(1) --#endif --struct set_user_access_data { --#if WORDS_BIGENDIAN -- uint8_t change_bits : 1; -- uint8_t callin_callback : 1; -- uint8_t link_auth : 1; -- uint8_t ipmi_messaging : 1; -- uint8_t channel : 4; -- uint8_t __reserved1 : 2; -- uint8_t user_id : 6; -- uint8_t __reserved2 : 4; -- uint8_t privilege_limit : 4; -- uint8_t __reserved3 : 4; -- uint8_t session_limit : 4; --#else -- uint8_t channel : 4; -- uint8_t ipmi_messaging : 1; -- uint8_t link_auth : 1; -- uint8_t callin_callback : 1; -- uint8_t change_bits : 1; -- uint8_t user_id : 6; -- uint8_t __reserved1 : 2; -- uint8_t privilege_limit : 4; -- uint8_t __reserved2 : 4; -- uint8_t session_limit : 4; -- uint8_t __reserved3 : 4; --#endif --} ATTRIBUTE_PACKING; --#ifdef HAVE_PRAGMA_PACK --#pragma pack(0) --#endif -+int _ipmi_get_channel_access(struct ipmi_intf *intf, -+ struct channel_access_t *channel_access, -+ uint8_t get_volatile_settings); -+int _ipmi_set_channel_access(struct ipmi_intf *intf, -+ struct channel_access_t channel_access, uint8_t access_option, -+ uint8_t privilege_option); - - uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel); - uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf); -diff --git a/include/ipmitool/ipmi_dcmi.h b/include/ipmitool/ipmi_dcmi.h -index ce90857..15a959f 100644 ---- a/include/ipmitool/ipmi_dcmi.h -+++ b/include/ipmitool/ipmi_dcmi.h -@@ -52,6 +52,53 @@ - #define GOOD_PWR_GLIMIT_CCODE(ccode) ((ccode = ((ccode == 0x80) ? 0 : ccode))) - #define GOOD_ASSET_TAG_CCODE(ccode) ((ccode = (((ccode == 0x80) || (ccode == 0x81) || (ccode == 0x82) || (ccode == 0x83)) ? 0 : ccode))) - -+/* External Node Manager Configuration and Control Commands per spec 2.0 */ -+ -+#define IPMI_NM_POLICY_CTL 0xC0 -+#define IPMI_NM_SET_POLICY 0xC1 -+#define IPMI_NM_GET_POLICY 0xC2 -+#define IPMI_NM_SET_ALERT_TH 0xC3 -+#define IPMI_NM_GET_ALERT_TH 0xC4 -+#define IPMI_NM_SET_SUSPEND 0xC5 -+#define IPMI_NM_GET_SUSPEND 0xC6 -+#define IPMI_NM_RESET_STATS 0xC7 -+#define IPMI_NM_GET_STATS 0xC8 -+#define IPMI_NM_GET_CAP 0xC9 -+#define IPMI_NM_GET_VERSION 0xCA -+#define IPMI_NM_SET_POWER 0xCB -+#define IPMI_NM_SET_ALERT_DS 0xCE -+#define IPMI_NM_GET_ALERT_DS 0xCF -+#define IPMI_NM_LIMITING 0xF2 -+ -+/* Node Manager Policy Control Flags */ -+#define IPMI_NM_GLOBAL_ENABLE 0x01 -+#define IPMI_NM_DOMAIN_ENABLE 0x02 -+#define IPMI_NM_PER_POLICY_ENABLE 0x04 -+ -+/* Node Manager Set Policy Enable */ -+#define IPMI_NM_POLICY_ENABLE 0x10 -+ -+/* Node Manager Policy Trigger Codes */ -+#define IPMI_NM_NO_POLICY_TRIG 0x00 -+#define IPMI_NM_TEMP_TRIGGER 0x01 -+#define IPMI_NM_NO_READ_TRIG 0x02 -+#define IPMI_NM_RESET_TRIGGER 0x03 -+#define IPMI_NM_BOOT_TRIGGER 0x04 -+ -+/* Policy Exception Actions flags */ -+#define IPMI_NM_POLICY_ALERT 0x01 -+#define IPMI_NM_POLICY_SHUT 0x02 -+ -+/* Power Correction codes for Policy action */ -+#define IPMI_NM_PWR_AUTO_CORR 0x00 -+#define IPMI_NM_PWR_SOFT_CORR 0x01 -+#define IPMI_NM_PWR_AGGR_CORR 0x02 -+ -+/* Set Threshold message size */ -+#define IPMI_NM_SET_THRESH_LEN 12 -+ -+/* Number of Suspend Periods */ -+#define IPMI_NM_SUSPEND_PERIOD_MAX 5 - - struct dcmi_cmd { - uint16_t val; -@@ -126,4 +173,98 @@ struct thermal_limit { - - int ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char ** argv); - -+/* Node Manager discover command */ -+struct nm_discover { -+ uint8_t intel_id[3]; /* Always returns 000157 */ -+ uint8_t nm_version; -+ uint8_t ipmi_version; -+ uint8_t patch_version; -+ uint8_t major_rev; -+ uint8_t minor_rev; -+} __attribute__ ((packed)); -+ -+/* Node Manager get capabilites command */ -+struct nm_capability { -+ uint8_t intel_id[3]; -+ uint8_t max_settings; -+ uint16_t max_value; /* max power/thermal/time after reset */ -+ uint16_t min_value; /* min "" */ -+ uint32_t min_corr; /* min correction time inmillesecs */ -+ uint32_t max_corr; -+ uint16_t min_stats; -+ uint16_t max_stats; -+ uint8_t scope; -+} __attribute__ ((packed)); -+ -+/* Node Manager get statistics command */ -+struct nm_statistics { -+ uint8_t intel_id[3]; -+ uint16_t curr_value; -+ uint16_t min_value; -+ uint16_t max_value; -+ uint16_t ave_value; -+ uint32_t time_stamp; -+ uint32_t stat_period; -+ uint8_t id_state; -+} __attribute__ ((packed)); -+ -+/* Node Manager set policy */ -+struct nm_policy { -+ uint8_t intel_id[3]; -+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */ -+ uint8_t policy_id; -+ uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */ -+ uint8_t policy_exception; /* exception actions */ -+ uint16_t policy_limits; -+ uint32_t corr_time; -+ uint16_t trigger_limit; -+ uint16_t stats_period; -+} __attribute__ ((packed)); -+ -+/* Node Maager get policy */ -+struct nm_get_policy { -+ uint8_t intel_id[3]; -+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */ -+ uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */ -+ uint8_t policy_exception; /* exception actions */ -+ uint16_t policy_limits; -+ uint32_t corr_time; -+ uint16_t trigger_limit; -+ uint16_t stats_period; -+} __attribute__ ((packed)); -+ -+/* Node Manager set alert destination */ -+struct nm_set_alert { -+ uint8_t intel_id[3]; -+ uint8_t chan; /* 0:3 BMC chan, 4:6 reserved, bit 7=0 register alert reciever =1 invalidate */ -+ uint8_t dest; /* lan destination */ -+ uint8_t string; /* alert string selector */ -+} __attribute__ ((packed)); -+ -+/* Node Manager set alert threshold */ -+struct nm_thresh { -+ uint8_t intel_id[3]; -+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */ -+ uint8_t policy_id; -+ uint8_t count; -+ uint16_t thresholds[3]; -+} __attribute__ ((packed)); -+ -+/* Node Manager suspend period struct */ -+struct nm_period { -+ uint8_t start; -+ uint8_t stop; -+ uint8_t repeat; -+} __attribute__ ((packed)); -+ -+/* Node Manager set suspend period */ -+struct nm_suspend { -+ uint8_t intel_id[3]; -+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */ -+ uint8_t policy_id; -+ uint8_t count; -+ struct nm_period period[IPMI_NM_SUSPEND_PERIOD_MAX]; -+} __attribute__ ((packed)); -+ -+int ipmi_nm_main(struct ipmi_intf * intf, int argc, char ** argv); - #endif /*IPMI_DCMI_H*/ -diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h -index f9f6592..efec82d 100644 ---- a/include/ipmitool/ipmi_intf.h -+++ b/include/ipmitool/ipmi_intf.h -@@ -62,36 +62,43 @@ enum LANPLUS_SESSION_STATE { - #define IPMI_SIK_BUFFER_SIZE 20 - #define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */ - --struct ipmi_session { -- char *hostname; /* Numeric IP adress or DNS name - see RFC 1034/RFC 1035 */ -+struct ipmi_session_params { -+ char * hostname; - uint8_t username[17]; -- uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1]; -- uint8_t challenge[16]; -- uint8_t authtype; -+ uint8_t authcode_set[IPMI_AUTHCODE_BUFFER_SIZE + 1]; - uint8_t authtype_set; --#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10 --#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08 --#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04 --#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02 --#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01 -- uint8_t authstatus; -- uint8_t authextra; - uint8_t privlvl; - uint8_t cipher_suite_id; - char sol_escape_char; - int password; - int port; -- int active; - int retry; -+ uint32_t timeout; -+ uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */ -+ uint8_t lookupbit; -+}; - -+#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10 -+#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08 -+#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04 -+#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02 -+#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01 -+ -+struct ipmi_session { -+ int active; - uint32_t session_id; - uint32_t in_seq; - uint32_t out_seq; -+ -+ uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1]; -+ uint8_t challenge[16]; -+ uint8_t authtype; -+ uint8_t authstatus; -+ uint8_t authextra; - uint32_t timeout; - - struct sockaddr_storage addr; - socklen_t addrlen; -- int ai_family; /* Protocol family for socket. */ - - /* - * This struct holds state data specific to IPMI v2 / RMCP+ sessions -@@ -107,7 +114,6 @@ struct ipmi_session { - uint8_t integrity_alg; - uint8_t crypt_alg; - uint8_t max_priv_level; -- uint8_t lookupbit; - - uint32_t console_id; - uint32_t bmc_id; -@@ -168,8 +174,10 @@ struct ipmi_intf { - int abort; - int noanswer; - int picmg_avail; -+ int vita_avail; - IPMI_OEM manufacturer_id; - -+ struct ipmi_session_params ssn_params; - struct ipmi_session * session; - struct ipmi_oem_handle * oem; - struct ipmi_cmd * cmdlist; -diff --git a/include/ipmitool/ipmi_lanp.h b/include/ipmitool/ipmi_lanp.h -index 1aaae5e..ba25582 100644 ---- a/include/ipmitool/ipmi_lanp.h -+++ b/include/ipmitool/ipmi_lanp.h -@@ -76,6 +76,8 @@ enum { - IPMI_LANP_RMCP_CIPHER_SUPPORT, - IPMI_LANP_RMCP_CIPHERS, - IPMI_LANP_RMCP_PRIV_LEVELS, -+ IPMI_LANP_VLAN_TAGS, -+ IPMI_LANP_BAD_PASS_THRESH, - IPMI_LANP_OEM_ALERT_STRING=96, - IPMI_LANP_ALERT_RETRY=97, - IPMI_LANP_UTC_OFFSET=98, -@@ -92,38 +94,39 @@ static struct lan_param { - uint8_t * data; - int data_len; - } ipmi_lan_params[] __attribute__((unused)) = { -- { IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress" }, -- { IPMI_LANP_AUTH_TYPE, 1, "Auth Type Support" }, -- { IPMI_LANP_AUTH_TYPE_ENABLE, 5, "Auth Type Enable" }, -- { IPMI_LANP_IP_ADDR, 4, "IP Address" }, -- { IPMI_LANP_IP_ADDR_SRC, 1, "IP Address Source" }, -- { IPMI_LANP_MAC_ADDR, 6, "MAC Address" }, /* 5 */ -- { IPMI_LANP_SUBNET_MASK, 4, "Subnet Mask" }, -- { IPMI_LANP_IP_HEADER, 3, "IP Header" }, -- { IPMI_LANP_PRI_RMCP_PORT, 2, "Primary RMCP Port" }, -- { IPMI_LANP_SEC_RMCP_PORT, 2, "Secondary RMCP Port" }, -- { IPMI_LANP_BMC_ARP, 1, "BMC ARP Control" }, /* 10 */ -- { IPMI_LANP_GRAT_ARP, 1, "Gratituous ARP Intrvl" }, -- { IPMI_LANP_DEF_GATEWAY_IP, 4, "Default Gateway IP" }, -- { IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC" }, -- { IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP" }, -- { IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC" }, /* 15 */ -- { IPMI_LANP_SNMP_STRING, 18, "SNMP Community String" }, -- { IPMI_LANP_NUM_DEST, 1, "Number of Destinations"}, -- { IPMI_LANP_DEST_TYPE, 4, "Destination Type" }, -- { IPMI_LANP_DEST_ADDR, 13, "Destination Addresses" }, -- { IPMI_LANP_VLAN_ID, 2, "802.1q VLAN ID" }, /* 20 */ -- { IPMI_LANP_VLAN_PRIORITY, 1, "802.1q VLAN Priority" }, -- { IPMI_LANP_RMCP_CIPHER_SUPPORT,1, "RMCP+ Cipher Suite Count" }, -- { IPMI_LANP_RMCP_CIPHERS, 16, "RMCP+ Cipher Suites" }, -- { IPMI_LANP_RMCP_PRIV_LEVELS, 9, "Cipher Suite Priv Max" }, -- { IPMI_LANP_OEM_ALERT_STRING, 28, "OEM Alert String" }, /* 25 */ -- { IPMI_LANP_ALERT_RETRY, 1, "Alert Retry Algorithm" }, -- { IPMI_LANP_UTC_OFFSET, 3, "UTC Offset" }, -- { IPMI_LANP_DHCP_SERVER_IP, 4, "DHCP Server IP" }, -- { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC" }, -- { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable" }, /* 30 */ -- { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode" }, -+ { IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress", NULL, 0 }, -+ { IPMI_LANP_AUTH_TYPE, 1, "Auth Type Support", NULL, 0 }, -+ { IPMI_LANP_AUTH_TYPE_ENABLE, 5, "Auth Type Enable", NULL, 0 }, -+ { IPMI_LANP_IP_ADDR, 4, "IP Address", NULL, 0 }, -+ { IPMI_LANP_IP_ADDR_SRC, 1, "IP Address Source", NULL, 0 }, -+ { IPMI_LANP_MAC_ADDR, 6, "MAC Address", NULL, 0 }, /* 5 */ -+ { IPMI_LANP_SUBNET_MASK, 4, "Subnet Mask", NULL, 0 }, -+ { IPMI_LANP_IP_HEADER, 3, "IP Header", NULL, 0 }, -+ { IPMI_LANP_PRI_RMCP_PORT, 2, "Primary RMCP Port", NULL, 0 }, -+ { IPMI_LANP_SEC_RMCP_PORT, 2, "Secondary RMCP Port", NULL, 0 }, -+ { IPMI_LANP_BMC_ARP, 1, "BMC ARP Control", NULL, 0}, /* 10 */ -+ { IPMI_LANP_GRAT_ARP, 1, "Gratituous ARP Intrvl", NULL, 0 }, -+ { IPMI_LANP_DEF_GATEWAY_IP, 4, "Default Gateway IP", NULL, 0 }, -+ { IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC", NULL, 0 }, -+ { IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP", NULL, 0 }, -+ { IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC", NULL, 0 }, /* 15 */ -+ { IPMI_LANP_SNMP_STRING, 18, "SNMP Community String", NULL, 0 }, -+ { IPMI_LANP_NUM_DEST, 1, "Number of Destinations", NULL, 0 }, -+ { IPMI_LANP_DEST_TYPE, 4, "Destination Type", NULL, 0 }, -+ { IPMI_LANP_DEST_ADDR, 13, "Destination Addresses", NULL, 0 }, -+ { IPMI_LANP_VLAN_ID, 2, "802.1q VLAN ID", NULL, 0 }, /* 20 */ -+ { IPMI_LANP_VLAN_PRIORITY, 1, "802.1q VLAN Priority", NULL, 0 }, -+ { IPMI_LANP_RMCP_CIPHER_SUPPORT,1, "RMCP+ Cipher Suite Count", NULL, 0 }, -+ { IPMI_LANP_RMCP_CIPHERS, 16, "RMCP+ Cipher Suites", NULL, 0 }, -+ { IPMI_LANP_RMCP_PRIV_LEVELS, 9, "Cipher Suite Priv Max", NULL, 0 }, -+ { IPMI_LANP_BAD_PASS_THRESH, 6, "Bad Password Threshold", NULL, 0 }, -+ { IPMI_LANP_OEM_ALERT_STRING, 28, "OEM Alert String", NULL, 0 }, /* 25 */ -+ { IPMI_LANP_ALERT_RETRY, 1, "Alert Retry Algorithm", NULL, 0 }, -+ { IPMI_LANP_UTC_OFFSET, 3, "UTC Offset", NULL, 0 }, -+ { IPMI_LANP_DHCP_SERVER_IP, 4, "DHCP Server IP", NULL, 0 }, -+ { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC", NULL, 0}, -+ { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable", NULL, 0 }, /* 30 */ -+ { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode", NULL, 0 }, - { -1 } - }; - -diff --git a/include/ipmitool/ipmi_mc.h b/include/ipmitool/ipmi_mc.h -index 5546a3a..a840f78 100644 ---- a/include/ipmitool/ipmi_mc.h -+++ b/include/ipmitool/ipmi_mc.h -@@ -157,6 +157,9 @@ struct ipm_get_watchdog_rsp { - #define IPMI_SYSINFO_SET0_SIZE 14 - #define IPMI_SYSINFO_SETN_SIZE 16 - -+/* System Information "Parameter selector" values: */ -+#define IPMI_SYSINFO_SET_STATE 0x00 -+#define IPMI_SYSINFO_SYSTEM_FW_VERSION 0x01 - #define IPMI_SYSINFO_HOSTNAME 0x02 - #define IPMI_SYSINFO_PRIMARY_OS_NAME 0x03 - #define IPMI_SYSINFO_OS_NAME 0x04 -diff --git a/include/ipmitool/ipmi_sel.h b/include/ipmitool/ipmi_sel.h -index cacdb2d..53a8c1f 100644 ---- a/include/ipmitool/ipmi_sel.h -+++ b/include/ipmitool/ipmi_sel.h -@@ -690,41 +690,41 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu - }; - - static uint16_t supermicro_x9dal[] = { -- 0x0635 -+ 0x0635, 0xFFFF - }; - - static uint16_t supermicro_x9db[] = { -- 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637 -+ 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0xFFFF - }; - - static uint16_t supermicro_x9sb[] = { -- 0x0651 -+ 0x0651, 0xFFFF - }; - - static uint16_t supermicro_x9[] = { -- 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651 -+ 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651, 0xFFFF - }; - - static uint16_t supermicro_b8[] = { -- 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e -+ 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xFFFF - }; - - static uint16_t supermicro_h8[] = { - 0xa111, 0x0408, 0x0811, 0x1411, 0x0911, 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, - 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, - 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, -- 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811 -+ 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811, 0xFFFF - }; - - static uint16_t supermicro_p8[] = { -- 0x6480, 0x7380, 0x6280, 0x7480, 0x5980 -+ 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xFFFF - }; - - static uint16_t supermicro_x8[] = { - 0xa880, 0x0403, 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, - 0x040a, 0xf280, 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, - 0x060c, 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, -- 0x061a, 0xf580, 0x062e, 0x0009 -+ 0x061a, 0xf580, 0x062e, 0x0009, 0xFFFF - }; - - static uint16_t supermicro_X8[] = { -@@ -736,7 +736,7 @@ static uint16_t supermicro_X8[] = { - 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f, - 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x060c, 0x0003, 0x040b, - 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e, -- 0x0009 -+ 0x0009, 0xFFFF - }; - - int ipmi_sel_main(struct ipmi_intf *, int, char **); -diff --git a/include/ipmitool/ipmi_user.h b/include/ipmitool/ipmi_user.h -index 4a8e481..fd727ca 100644 ---- a/include/ipmitool/ipmi_user.h -+++ b/include/ipmitool/ipmi_user.h -@@ -38,58 +38,46 @@ - #endif - #include - -+#define IPMI_PASSWORD_DISABLE_USER 0x00 -+#define IPMI_PASSWORD_ENABLE_USER 0x01 -+#define IPMI_PASSWORD_SET_PASSWORD 0x02 -+#define IPMI_PASSWORD_TEST_PASSWORD 0x03 - --/* -- * The GET USER ACCESS response from table 22-32 of the IPMI v2.0 spec -- */ --struct user_access_rsp { --#if WORDS_BIGENDIAN -- uint8_t __reserved1 : 2; -- uint8_t maximum_ids : 6; --#else -- uint8_t maximum_ids : 6; -- uint8_t __reserved1 : 2; --#endif -- --#if WORDS_BIGENDIAN -- uint8_t __reserved2 : 2; -- uint8_t enabled_user_count : 6; --#else -- uint8_t enabled_user_count : 6; -- uint8_t __reserved2 : 2; --#endif -- --#if WORDS_BIGENDIAN -- uint8_t __reserved3 : 2; -- uint8_t fixed_name_count : 6; --#else -- uint8_t fixed_name_count : 6; -- uint8_t __reserved3 : 2; --#endif -- --#ifdef HAVE_PRAGMA_PACK --#pragma pack(1) --#endif --#if WORDS_BIGENDIAN -- uint8_t __reserved4 : 1; -- uint8_t no_callin_access : 1; -- uint8_t link_auth_access : 1; -- uint8_t ipmi_messaging_access : 1; -- uint8_t channel_privilege_limit : 4; --#else -- uint8_t channel_privilege_limit : 4; -- uint8_t ipmi_messaging_access : 1; -- uint8_t link_auth_access : 1; -- uint8_t no_callin_access : 1; -- uint8_t __reserved4 : 1; --#endif --} ATTRIBUTE_PACKING; --#ifdef HAVE_PRAGMA_PACK --#pragma pack(0) --#endif -+#define IPMI_USER_ENABLE_UNSPECIFIED 0x00 -+#define IPMI_USER_ENABLE_ENABLED 0x40 -+#define IPMI_USER_ENABLE_DISABLED 0x80 -+#define IPMI_USER_ENABLE_RESERVED 0xC0 - -+/* (22.27) Get and (22.26) Set User Access */ -+struct user_access_t { -+ uint8_t callin_callback; -+ uint8_t channel; -+ uint8_t enabled_user_ids; -+ uint8_t enable_status; -+ uint8_t fixed_user_ids; -+ uint8_t ipmi_messaging; -+ uint8_t link_auth; -+ uint8_t max_user_ids; -+ uint8_t privilege_limit; -+ uint8_t session_limit; -+ uint8_t user_id; -+}; - -+/* (22.29) Get User Name */ -+struct user_name_t { -+ uint8_t user_id; -+ uint8_t user_name[17]; -+}; - - int ipmi_user_main(struct ipmi_intf *, int, char **); -+int _ipmi_get_user_access(struct ipmi_intf *intf, -+ struct user_access_t *user_access_rsp); -+int _ipmi_get_user_name(struct ipmi_intf *intf, struct user_name_t *user_name); -+int _ipmi_set_user_access(struct ipmi_intf *intf, -+ struct user_access_t *user_access_req, -+ uint8_t change_priv_limit_only); -+int _ipmi_set_user_password(struct ipmi_intf *intf, -+ uint8_t user_id, uint8_t operation, -+ const char *password, uint8_t is_twenty_byte); - - #endif /* IPMI_USER_H */ -diff --git a/include/ipmitool/ipmi_vita.h b/include/ipmitool/ipmi_vita.h -new file mode 100644 -index 0000000..71d471a ---- /dev/null -+++ b/include/ipmitool/ipmi_vita.h -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) Pigeon Point Systems. All right reserved -+ */ -+ -+#ifndef _IPMI_VITA_H_ -+#define _IPMI_VITA_H_ -+ -+/* VITA 46.11 commands */ -+#define VITA_GET_VSO_CAPABILITIES_CMD 0x00 -+#define VITA_FRU_CONTROL_CMD 0x04 -+#define VITA_GET_FRU_LED_PROPERTIES_CMD 0x05 -+#define VITA_GET_LED_COLOR_CAPABILITIES_CMD 0x06 -+#define VITA_SET_FRU_LED_STATE_CMD 0x07 -+#define VITA_GET_FRU_LED_STATE_CMD 0x08 -+#define VITA_SET_FRU_STATE_POLICY_BITS_CMD 0x0A -+#define VITA_GET_FRU_STATE_POLICY_BITS_CMD 0x0B -+#define VITA_SET_FRU_ACTIVATION_CMD 0x0C -+#define VITA_GET_FRU_ADDRESS_INFO_CMD 0x40 -+ -+/* VITA 46.11 site types */ -+#define VITA_FRONT_VPX_MODULE 0x00 -+#define VITA_POWER_ENTRY 0x01 -+#define VITA_CHASSIS_FRU 0x02 -+#define VITA_DEDICATED_CHMC 0x03 -+#define VITA_FAN_TRAY 0x04 -+#define VITA_FAN_TRAY_FILTER 0x05 -+#define VITA_ALARM_PANEL 0x06 -+#define VITA_XMC 0x07 -+#define VITA_VPX_RTM 0x09 -+#define VITA_FRONT_VME_MODULE 0x0A -+#define VITA_FRONT_VXS_MODULE 0x0B -+#define VITA_POWER_SUPPLY 0x0C -+#define VITA_FRONT_VITA62_MODULE 0x0D -+#define VITA_71_MODULE 0x0E -+#define VITA_FMC 0x0F -+ -+ -+#define GROUP_EXT_VITA 0x03 -+ -+extern uint8_t -+vita_discover(struct ipmi_intf *intf); -+ -+extern uint8_t -+ipmi_vita_ipmb_address(struct ipmi_intf *intf); -+ -+extern int -+ipmi_vita_main(struct ipmi_intf * intf, int argc, char ** argv); -+ -+#endif /* _IPMI_VITA_H_ */ -diff --git a/lib/Makefile.am b/lib/Makefile.am -index d878b11..2a316db 100644 ---- a/lib/Makefile.am -+++ b/lib/Makefile.am -@@ -39,7 +39,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \ - ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.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_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c ipmi_vita.c \ - ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h - - libipmitool_la_LDFLAGS = -export-dynamic -diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c -index 91ae117..912b211 100644 ---- a/lib/dimm_spd.c -+++ b/lib/dimm_spd.c -@@ -867,9 +867,11 @@ ipmi_spd_print(uint8_t *spd_data, int len) - int sdram_width = 0; - int mem_size = 0; - int lrank_dimm; -+ uint32_t year; -+ uint32_t week; - -- if (len < 148) -- return -1; /* we need first 91 bytes to do our thing */ -+ if (len < 348) -+ return -1; - - /* "Logical rank" referes to the individually addressable die - * in a 3DS stack and has no meaning for monolithic or -@@ -879,7 +881,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) - * rank per package rank. - */ - lrank_dimm = (spd_data[12]>>3&0x3) + 1; /* Number of Package Ranks per DIMM */ -- if ((spd_data[6] & 0x3) == 0x10) { /* 3DS package Type */ -+ if ((spd_data[6] & 0x3) == 0x2) { /* 3DS package Type */ - lrank_dimm *= ((spd_data[6]>>4)&0x3) + 1; /* Die Count */ - } - sdram_cap = ldexp(256,(spd_data[4]&15)); -@@ -931,8 +933,8 @@ ipmi_spd_print(uint8_t *spd_data, int len) - - } - -- u_int year = (spd_data[323]>>4)*10 + spd_data[323]&15; -- u_int week = (spd_data[324]>>4)*10 + spd_data[324]&15; -+ year = ((spd_data[323] >> 4) * 10) + (spd_data[323] & 15); -+ week = ((spd_data[324]>>4) * 10) + (spd_data[324] & 15); - printf(" Manufacture Date : year %4d week %2d\n", - 2000 + year, week); - -@@ -948,6 +950,9 @@ ipmi_spd_print(uint8_t *spd_data, int len) - } - else - { -+ if (len < 100) { -+ return (-1); -+ } - ii = (spd_data[3] & 0x0f) + (spd_data[4] & 0x0f) - 17; - k = ((spd_data[5] & 0x7) + 1) * spd_data[17]; - -@@ -1064,7 +1069,6 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) - offset = 0; - memset(spd_data, 0, fru.size); - do { -- int i; - msg_data[0] = id; - msg_data[1] = offset & 0xFF; - msg_data[2] = offset >> 8; -diff --git a/lib/helper.c b/lib/helper.c -index 95d641e..b9316c4 100644 ---- a/lib/helper.c -+++ b/lib/helper.c -@@ -29,6 +29,7 @@ - * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, - * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ -+#define _POSIX_SOURCE - - #include - #include -@@ -671,6 +672,43 @@ ipmi_start_daemon(struct ipmi_intf *intf) - dup(fd); - } - -+/* eval_ccode - evaluate return value of _ipmi_* functions and print error error -+ * message, if conditions are met. -+ * -+ * @ccode - return value of _ipmi_* function. -+ * -+ * returns - 0 if ccode is 0, otherwise (-1) and error might get printed-out. -+ */ -+int -+eval_ccode(const int ccode) -+{ -+ if (ccode == 0) { -+ return 0; -+ } else if (ccode < 0) { -+ switch (ccode) { -+ case (-1): -+ lprintf(LOG_ERR, "IPMI response is NULL."); -+ break; -+ case (-2): -+ lprintf(LOG_ERR, "Unexpected data length received."); -+ break; -+ case (-3): -+ lprintf(LOG_ERR, "Invalid function parameter."); -+ break; -+ case (-4): -+ lprintf(LOG_ERR, "ipmitool: malloc failure."); -+ break; -+ default: -+ break; -+ } -+ return (-1); -+ } else { -+ lprintf(LOG_ERR, "IPMI command failed: %s", -+ val2str(ccode, completion_code_vals)); -+ return (-1); -+ } -+} -+ - /* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed - * on error. - * FRU ID range: <0..255> -@@ -700,9 +738,9 @@ is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr) - /* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is - * printed on error. - * -- * 6.3 Channel Numbers, p. 45, IPMIv2 spec. -- * Valid channel numbers are: <0..7>, -- * Reserved channel numbers: <8-D> -+ * 6.3 Channel Numbers, p. 49, IPMIv2 spec. rev1.1 -+ * Valid channel numbers are: <0x0..0xB>, <0xE-0xF> -+ * Reserved channel numbers: <0xC-0xD> - * - * @argv_ptr: source string to convert from; usually argv - * @channel_ptr: pointer where to store result -@@ -719,14 +757,14 @@ is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr) - return (-1); - } - if ((str2uchar(argv_ptr, channel_ptr) == 0) -- && ((*channel_ptr >= 0x0 && *channel_ptr <= 0x7) -+ && (*channel_ptr <= 0xB - || (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) { - return 0; - } - lprintf(LOG_ERR, - "Given Channel number '%s' is either invalid or out of range.", - argv_ptr); -- lprintf(LOG_ERR, "Channel number must be from ranges: <0..7>, <0xE..0xF>"); -+ lprintf(LOG_ERR, "Channel number must be from ranges: <0x0..0xB>, <0xE..0xF>"); - return (-1); - } - -@@ -760,6 +798,36 @@ is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr) - return (-1); - } - -+/* is_ipmi_user_priv_limit - check whether given value is valid User Privilege -+ * Limit, eg. IPMI v2 spec, 22.27 Get User Access Command. -+ * -+ * @priv_limit: User Privilege Limit -+ * -+ * returns 0 if Priv Limit is valid -+ * returns (-1) when Priv Limit is invalid -+ */ -+int -+is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr) -+{ -+ if (!argv_ptr || !ipmi_priv_limit_ptr) { -+ lprintf(LOG_ERR, -+ "is_ipmi_user_priv_limit(): invalid argument(s)."); -+ return (-1); -+ } -+ if ((str2uchar(argv_ptr, ipmi_priv_limit_ptr) != 0) -+ || ((*ipmi_priv_limit_ptr < 0x01 -+ || *ipmi_priv_limit_ptr > 0x05) -+ && *ipmi_priv_limit_ptr != 0x0F)) { -+ lprintf(LOG_ERR, -+ "Given Privilege Limit '%s' is invalid.", -+ argv_ptr); -+ lprintf(LOG_ERR, -+ "Privilege Limit is limited to <0x1..0x5> and <0xF>."); -+ return (-1); -+ } -+ return 0; -+} -+ - uint16_t - ipmi_get_oem_id(struct ipmi_intf *intf) - { -diff --git a/lib/hpm2.c b/lib/hpm2.c -index 6cb2f80..6420629 100644 ---- a/lib/hpm2.c -+++ b/lib/hpm2.c -@@ -213,8 +213,8 @@ int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, - /* send */ - rsp = intf->sendrecv(intf, &req); - -- if (rsp) { -- lprintf(LOG_NOTICE, "Error sending request"); -+ if (!rsp) { -+ lprintf(LOG_NOTICE, "Error sending request."); - return -1; - } - -diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c -index 43db338..95017b8 100644 ---- a/lib/ipmi_channel.c -+++ b/lib/ipmi_channel.c -@@ -50,11 +50,176 @@ - #include - #include - #include -+#include - - extern int csv_output; - extern int verbose; - --void printf_channel_usage (void); -+void printf_channel_usage(void); -+ -+/* _ipmi_get_channel_access - Get Channel Access for given channel. Results are -+ * stored into passed struct. -+ * -+ * @intf - IPMI interface -+ * @channel_access - ptr to channel_access_t with Channel set. -+ * @get_volatile_settings - get volatile if != 0, else non-volatile settings. -+ * -+ * returns - negative number means error, positive is a ccode. -+ */ -+int -+_ipmi_get_channel_access(struct ipmi_intf *intf, -+ struct channel_access_t *channel_access, -+ uint8_t get_volatile_settings) -+{ -+ struct ipmi_rs *rsp; -+ struct ipmi_rq req = {0}; -+ uint8_t data[2]; -+ -+ if (channel_access == NULL) { -+ return (-3); -+ } -+ data[0] = channel_access->channel & 0x0F; -+ /* volatile - 0x80; non-volatile - 0x40 */ -+ data[1] = get_volatile_settings ? 0x80 : 0x40; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; -+ req.msg.data = data; -+ req.msg.data_len = 2; -+ -+ 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); -+ } -+ channel_access->alerting = rsp->data[0] & 0x20; -+ channel_access->per_message_auth = rsp->data[0] & 0x10; -+ channel_access->user_level_auth = rsp->data[0] & 0x08; -+ channel_access->access_mode = rsp->data[0] & 0x07; -+ channel_access->privilege_limit = rsp->data[1] & 0x0F; -+ return 0; -+} -+ -+/* _ipmi_get_channel_info - Get Channel Info for given channel. Results are -+ * stored into passed struct. -+ * -+ * @intf - IPMI interface -+ * @channel_info - ptr to channel_info_t with Channel set. -+ * -+ * returns - negative number means error, positive is a ccode. -+ */ -+int -+_ipmi_get_channel_info(struct ipmi_intf *intf, -+ struct channel_info_t *channel_info) -+{ -+ struct ipmi_rs *rsp; -+ struct ipmi_rq req = {0}; -+ uint8_t data[1]; -+ -+ if (channel_info == NULL) { -+ return (-3); -+ } -+ data[0] = channel_info->channel & 0x0F; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_CHANNEL_INFO; -+ req.msg.data = data; -+ req.msg.data_len = 1; -+ -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ return (-1); -+ } else if (rsp->ccode != 0) { -+ return rsp->ccode; -+ } else if (rsp->data_len != 9) { -+ return (-2); -+ } -+ channel_info->channel = rsp->data[0] & 0x0F; -+ channel_info->medium = rsp->data[1] & 0x7F; -+ channel_info->protocol = rsp->data[2] & 0x1F; -+ channel_info->session_support = rsp->data[3] & 0xC0; -+ channel_info->active_sessions = rsp->data[3] & 0x3F; -+ memcpy(channel_info->vendor_id, &rsp->data[4], -+ sizeof(channel_info->vendor_id)); -+ memcpy(channel_info->aux_info, &rsp->data[7], -+ sizeof(channel_info->aux_info)); -+ return 0; -+} -+ -+/* _ipmi_set_channel_access - Set Channel Access values for given channel. -+ * -+ * @intf - IPMI interface -+ * @channel_access - channel_access_t with desired values and channel set. -+ * @access_option: -+ * - 0 = don't set/change Channel Access -+ * - 1 = set non-volatile settings of Channel Access -+ * - 2 = set volatile settings of Channel Access -+ * @privilege_option: -+ * - 0 = don't set/change Privilege Level Limit -+ * - 1 = set non-volatile settings of Privilege Limit -+ * - 2 = set volatile settings of Privilege Limit -+ * -+ * returns - negative number means error, positive is a ccode. See IPMI -+ * specification for further information on ccodes for Set Channel Access. -+ * 0x82 - set not supported on selected channel, eg. session-less channel. -+ * 0x83 - access mode not supported -+ */ -+int -+_ipmi_set_channel_access(struct ipmi_intf *intf, -+ struct channel_access_t channel_access, -+ uint8_t access_option, -+ uint8_t privilege_option) -+{ -+ struct ipmi_rs *rsp; -+ struct ipmi_rq req; -+ uint8_t data[3]; -+ /* Only values from <0..2> are accepted as valid. */ -+ if (access_option > 2 || privilege_option > 2) { -+ return (-3); -+ } -+ -+ memset(&data, 0, sizeof(data)); -+ data[0] = channel_access.channel & 0x0F; -+ data[1] = (access_option << 6); -+ if (channel_access.alerting) { -+ data[1] |= 0x20; -+ } -+ if (channel_access.per_message_auth) { -+ data[1] |= 0x10; -+ } -+ if (channel_access.user_level_auth) { -+ data[1] |= 0x08; -+ } -+ data[1] |= (channel_access.access_mode & 0x07); -+ data[2] = (privilege_option << 6); -+ data[2] |= (channel_access.privilege_limit & 0x0F); -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_SET_CHANNEL_ACCESS; -+ req.msg.data = data; -+ req.msg.data_len = 3; -+ -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ return (-1); -+ } -+ return rsp->ccode; -+} -+ -+static const char * -+iana_string(uint32_t iana) -+{ -+ static char s[10]; -+ -+ if (iana) { -+ sprintf(s, "%06x", iana); -+ return s; -+ } else { -+ return "N/A"; -+ } -+} - - /** - * ipmi_1_5_authtypes -@@ -68,8 +233,7 @@ ipmi_1_5_authtypes(uint8_t n) - uint32_t i; - static char supportedTypes[128]; - -- bzero(supportedTypes, 128); -- -+ memset(supportedTypes, 0, sizeof(supportedTypes)); - for (i = 0; ipmi_authtype_vals[i].val != 0; i++) { - if (n & ipmi_authtype_vals[i].val) { - strcat(supportedTypes, ipmi_authtype_vals[i].str); -@@ -80,7 +244,11 @@ ipmi_1_5_authtypes(uint8_t n) - return supportedTypes; - } - -- -+uint8_t -+ipmi_current_channel_medium(struct ipmi_intf *intf) -+{ -+ return ipmi_get_channel_medium(intf, 0xE); -+} - - /** - * ipmi_get_channel_auth_cap -@@ -89,27 +257,26 @@ ipmi_1_5_authtypes(uint8_t n) - * -1 on failure - */ - int --ipmi_get_channel_auth_cap(struct ipmi_intf * intf, -- uint8_t channel, -- uint8_t priv) -+ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv) - { -- struct ipmi_rs * rsp; -+ struct ipmi_rs *rsp; - struct ipmi_rq req; - struct get_channel_auth_cap_rsp auth_cap; - uint8_t msg_data[2]; - -- msg_data[0] = channel | 0x80; // Ask for IPMI v2 data as well -+ /* Ask for IPMI v2 data as well */ -+ msg_data[0] = channel | 0x80; - msg_data[1] = priv; - - memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; // 0x06 -- req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38 -- req.msg.data = msg_data; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; -+ req.msg.data = msg_data; - req.msg.data_len = 2; - - rsp = intf->sendrecv(intf, &req); - -- if ((rsp == NULL) || (rsp->ccode > 0)) { -+ if ((rsp == NULL) || (rsp->ccode > 0)) { - /* - * It's very possible that this failed because we asked for IPMI v2 data - * Ask again, without requesting IPMI v2 data -@@ -119,12 +286,12 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { - lprintf(LOG_ERR, "Unable to Get Channel Authentication Capabilities"); -- return -1; -+ return (-1); - } - if (rsp->ccode > 0) { - lprintf(LOG_ERR, "Get Channel Authentication Capabilities failed: %s", - val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ return (-1); - } - } - -@@ -135,9 +302,10 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, - printf("IPMI v1.5 auth types : %s\n", - ipmi_1_5_authtypes(auth_cap.enabled_auth_types)); - -- if (auth_cap.v20_data_available) -+ if (auth_cap.v20_data_available) { - printf("KG status : %s\n", - (auth_cap.kg_status) ? "non-zero" : "default (all zeroes)"); -+ } - - printf("Per message authentication : %sabled\n", - (auth_cap.per_message_auth) ? "dis" : "en"); -@@ -174,118 +342,252 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, - return 0; - } - -- -- --/** -- * ipmi_get_channel_info -- * -- * returns 0 on success -- * -1 on failure -- * -- */ --int --ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) -+static int -+ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type, -+ uint8_t channel) - { -- struct ipmi_rs * rsp; -+ struct ipmi_rs *rsp; - struct ipmi_rq req; -- uint8_t rqdata[2]; -- uint8_t medium; -- struct get_channel_info_rsp channel_info; -- struct get_channel_access_rsp channel_access; - -+ uint8_t rqdata[3]; -+ uint32_t iana; -+ uint8_t auth_alg, integrity_alg, crypt_alg; -+ uint8_t cipher_suite_id; -+ uint8_t list_index = 0; -+ /* 0x40 sets * 16 bytes per set */ -+ uint8_t cipher_suite_data[1024]; -+ uint16_t offset = 0; -+ /* how much was returned, total */ -+ uint16_t cipher_suite_data_length = 0; -+ -+ memset(cipher_suite_data, 0, sizeof(cipher_suite_data)); -+ - memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; // 0x06 -- req.msg.cmd = IPMI_GET_CHANNEL_INFO; // 0x42 -- req.msg.data = &channel; -- req.msg.data_len = 1; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; -+ req.msg.data = rqdata; -+ req.msg.data_len = 3; -+ -+ rqdata[0] = channel; -+ rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1); -+ /* Always ask for cipher suite format */ -+ rqdata[2] = 0x80; - - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Info"); -+ lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); - return -1; - } - if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Info failed: %s", -+ lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", - val2str(rsp->ccode, completion_code_vals)); - return -1; - } - -- memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp)); - -- printf("Channel 0x%x info:\n", channel_info.channel_number); -+ /* -+ * Grab the returned channel number once. We assume it's the same -+ * in future calls. -+ */ -+ if (rsp->data_len >= 1) { -+ channel = rsp->data[0]; -+ } - -- printf(" Channel Medium Type : %s\n", -- val2str(channel_info.channel_medium, ipmi_channel_medium_vals)); -+ while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) { -+ /* -+ * We got back cipher suite data -- store it. -+ * printf("copying data to offset %d\n", offset); -+ * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); -+ */ -+ memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); -+ offset += rsp->data_len - 1; -+ -+ /* -+ * Increment our list for the next call -+ */ -+ ++list_index; -+ rqdata[2] = (rqdata[2] & 0x80) + list_index; - -- printf(" Channel Protocol Type : %s\n", -- val2str(channel_info.channel_protocol, ipmi_channel_protocol_vals)); -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); -+ return -1; -+ } -+ if (rsp->ccode > 0) { -+ lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", -+ val2str(rsp->ccode, completion_code_vals)); -+ return -1; -+ } -+ } -+ -+ /* Copy last chunk */ -+ if(rsp->data_len > 1) { -+ /* -+ * We got back cipher suite data -- store it. -+ * printf("copying data to offset %d\n", offset); -+ * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); -+ */ -+ memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); -+ offset += rsp->data_len - 1; -+ } -+ -+ /* We can chomp on all our data now. */ -+ cipher_suite_data_length = offset; -+ offset = 0; -+ -+ if (! csv_output) { -+ printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n"); -+ } -+ while (offset < cipher_suite_data_length) { -+ if (cipher_suite_data[offset++] == 0xC0) { -+ /* standard type */ -+ iana = 0; -+ -+ /* Verify that we have at least a full record left; id + 3 algs */ -+ if ((cipher_suite_data_length - offset) < 4) { -+ lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); -+ return -1; -+ } -+ cipher_suite_id = cipher_suite_data[offset++]; -+ } else if (cipher_suite_data[offset++] == 0xC1) { -+ /* OEM record type */ -+ /* Verify that we have at least a full record left -+ * id + iana + 3 algs -+ */ -+ if ((cipher_suite_data_length - offset) < 4) { -+ lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); -+ return -1; -+ } -+ -+ cipher_suite_id = cipher_suite_data[offset++]; -+ -+ /* Grab the IANA */ -+ iana = -+ cipher_suite_data[offset] | -+ (cipher_suite_data[offset + 1] << 8) | -+ (cipher_suite_data[offset + 2] << 16); -+ offset += 3; -+ } else { -+ lprintf(LOG_ERR, "Bad start of record byte in cipher suite data"); -+ return -1; -+ } -+ -+ /* -+ * Grab the algorithms for this cipher suite. I guess we can't be -+ * sure of what order they'll come in. Also, I suppose we default -+ * to the NONE algorithm if one were absent. This part of the spec is -+ * poorly written -- I have read the errata document. For now, I'm only -+ * allowing one algorithm per type (auth, integrity, crypt) because I -+ * don't I understand how it could be otherwise. -+ */ -+ auth_alg = IPMI_AUTH_RAKP_NONE; -+ integrity_alg = IPMI_INTEGRITY_NONE; -+ crypt_alg = IPMI_CRYPT_NONE; -+ -+ while (((cipher_suite_data[offset] & 0xC0) != 0xC0) && -+ ((cipher_suite_data_length - offset) > 0)) -+ { -+ switch (cipher_suite_data[offset] & 0xC0) -+ { -+ case 0x00: -+ /* Authentication algorithm specifier */ -+ auth_alg = cipher_suite_data[offset++] & 0x3F; -+ break; -+ case 0x40: -+ /* Interity algorithm specifier */ -+ integrity_alg = cipher_suite_data[offset++] & 0x3F; -+ break; -+ case 0x80: -+ /* Confidentiality algorithm specifier */ -+ crypt_alg = cipher_suite_data[offset++] & 0x3F; -+ break; -+ } -+ } -+ /* We have everything we need to spit out a cipher suite record */ -+ printf((csv_output? "%d,%s,%s,%s,%s\n" : -+ "%-4d %-7s %-15s %-15s %-15s\n"), -+ cipher_suite_id, -+ iana_string(iana), -+ val2str(auth_alg, ipmi_auth_algorithms), -+ val2str(integrity_alg, ipmi_integrity_algorithms), -+ val2str(crypt_alg, ipmi_encryption_algorithms)); -+ } -+ return 0; -+} -+ -+/** -+ * ipmi_get_channel_info -+ * -+ * returns 0 on success -+ * -1 on failure -+ * -+ */ -+int -+ipmi_get_channel_info(struct ipmi_intf *intf, uint8_t channel) -+{ -+ struct channel_info_t channel_info = {0}; -+ struct channel_access_t channel_access = {0}; -+ int ccode = 0; -+ -+ channel_info.channel = channel; -+ ccode = _ipmi_get_channel_info(intf, &channel_info); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Unable to Get Channel Info"); -+ return (-1); -+ } - -+ printf("Channel 0x%x info:\n", channel_info.channel); -+ printf(" Channel Medium Type : %s\n", -+ val2str(channel_info.medium, -+ ipmi_channel_medium_vals)); -+ printf(" Channel Protocol Type : %s\n", -+ val2str(channel_info.protocol, -+ ipmi_channel_protocol_vals)); - printf(" Session Support : "); - switch (channel_info.session_support) { -- case 0x0: -+ case IPMI_CHANNEL_SESSION_LESS: - printf("session-less\n"); - break; -- case 0x1: -+ case IPMI_CHANNEL_SESSION_SINGLE: - printf("single-session\n"); - break; -- case 0x2: -+ case IPMI_CHANNEL_SESSION_MULTI: - printf("multi-session\n"); - break; -- case 0x3: -- default: -+ case IPMI_CHANNEL_SESSION_BASED: - printf("session-based\n"); - break; -+ default: -+ printf("unknown\n"); -+ break; - } -- - printf(" Active Session Count : %d\n", - channel_info.active_sessions); -- - printf(" Protocol Vendor ID : %d\n", - channel_info.vendor_id[0] | - channel_info.vendor_id[1] << 8 | - channel_info.vendor_id[2] << 16); - -- - /* only proceed if this is LAN channel */ -- medium = ipmi_get_channel_medium(intf, channel); -- if (medium != IPMI_CHANNEL_MEDIUM_LAN && -- medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) { -+ if (channel_info.medium != IPMI_CHANNEL_MEDIUM_LAN -+ && channel_info.medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) { - return 0; - } - -- memset(&req, 0, sizeof(req)); -- rqdata[0] = channel & 0xf; -- -- /* get volatile settings */ -- -- rqdata[1] = 0x80; /* 0x80=active */ -- req.msg.netfn = IPMI_NETFN_APP; // 0x06 -- req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; // 0x41 -- req.msg.data = rqdata; -- req.msg.data_len = 2; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -+ channel_access.channel = channel_info.channel; -+ ccode = _ipmi_get_channel_access(intf, &channel_access, 1); -+ if (eval_ccode(ccode) != 0) { - lprintf(LOG_ERR, "Unable to Get Channel Access (volatile)"); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Access (volatile) failed: %s", -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ return (-1); - } - -- memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp)); -- -- - printf(" Volatile(active) Settings\n"); - printf(" Alerting : %sabled\n", -- (channel_access.alerting) ? "dis" : "en"); -+ (channel_access.alerting) ? "dis" : "en"); - printf(" Per-message Auth : %sabled\n", -- (channel_access.per_message_auth) ? "dis" : "en"); -+ (channel_access.per_message_auth) ? "dis" : "en"); - printf(" User Level Auth : %sabled\n", -- (channel_access.user_level_auth) ? "dis" : "en"); -- -+ (channel_access.user_level_auth) ? "dis" : "en"); - printf(" Access Mode : "); - switch (channel_access.access_mode) { - case 0: -@@ -305,30 +607,22 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) - break; - } - -+ memset(&channel_access, 0, sizeof(channel_access)); -+ channel_access.channel = channel_info.channel; - /* get non-volatile settings */ -- -- rqdata[1] = 0x40; /* 0x40=non-volatile */ -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0); -+ if (eval_ccode(ccode) != 0) { - lprintf(LOG_ERR, "Unable to Get Channel Access (non-volatile)"); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Access (non-volatile) failed: %s", -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ return (-1); - } - -- memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp)); -- - printf(" Non-Volatile Settings\n"); - printf(" Alerting : %sabled\n", -- (channel_access.alerting) ? "dis" : "en"); -+ (channel_access.alerting) ? "dis" : "en"); - printf(" Per-message Auth : %sabled\n", -- (channel_access.per_message_auth) ? "dis" : "en"); -+ (channel_access.per_message_auth) ? "dis" : "en"); - printf(" User Level Auth : %sabled\n", -- (channel_access.user_level_auth) ? "dis" : "en"); -- -+ (channel_access.user_level_auth) ? "dis" : "en"); - printf(" Access Mode : "); - switch (channel_access.access_mode) { - case 0: -@@ -347,66 +641,79 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) - printf("unknown\n"); - break; - } -- - return 0; - } - --static int --ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) -+/* ipmi_get_channel_medium - Return Medium of given IPMI Channel. -+ * -+ * @channel - IPMI Channel -+ * -+ * returns - IPMI Channel Medium, IPMI_CHANNEL_MEDIUM_RESERVED if ccode > 0, -+ * 0 on error. -+ */ -+uint8_t -+ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req1, req2; -- uint8_t rqdata[2]; -- struct get_user_access_rsp user_access; -- int curr_uid, max_uid = 0, init = 1; -- -- curr_uid = userid ? : 1; -- -- memset(&req1, 0, sizeof(req1)); -- req1.msg.netfn = IPMI_NETFN_APP; -- req1.msg.cmd = IPMI_GET_USER_ACCESS; -- req1.msg.data = rqdata; -- req1.msg.data_len = 2; -- -- memset(&req2, 0, sizeof(req2)); -- req2.msg.netfn = IPMI_NETFN_APP; -- req2.msg.cmd = IPMI_GET_USER_NAME; -- req2.msg.data = rqdata; -- req2.msg.data_len = 1; -- -- do -- { -- rqdata[0] = channel & 0xf; -- rqdata[1] = curr_uid & 0x3f; -- -- rsp = intf->sendrecv(intf, &req1); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)", -- rqdata[0], rqdata[1]); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s", -- rqdata[0], rqdata[1], -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -+ struct channel_info_t channel_info = {0}; -+ int ccode = 0; - -- memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); -- -- rqdata[0] = curr_uid & 0x3f; -+ channel_info.channel = channel; -+ ccode = _ipmi_get_channel_info(intf, &channel_info); -+ if (ccode == 0xCC) { -+ return IPMI_CHANNEL_MEDIUM_RESERVED; -+ } else if (ccode < 0 && eval_ccode(ccode) != 0) { -+ return 0; -+ } else if (ccode > 0) { -+ lprintf(LOG_ERR, "Get Channel Info command failed: %s", -+ val2str(ccode, completion_code_vals)); -+ return IPMI_CHANNEL_MEDIUM_RESERVED; -+ } -+ lprintf(LOG_DEBUG, "Channel type: %s", -+ val2str(channel_info.medium, ipmi_channel_medium_vals)); -+ return channel_info.medium; -+} - -- rsp = intf->sendrecv(intf, &req2); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get User Name (id %d)", rqdata[0]); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get User Name (id %d) failed: %s", -- rqdata[0], val2str(rsp->ccode, completion_code_vals)); -- return -1; -+/* ipmi_get_user_access - Get User Access for given Channel and User or Users. -+ * -+ * @intf - IPMI interface -+ * @channel - IPMI Channel we're getting access for -+ * @user_id - User ID. If 0 is passed, all IPMI users will be listed -+ * -+ * returns - 0 on success, (-1) on error -+ */ -+static int -+ipmi_get_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) -+{ -+ struct user_access_t user_access; -+ struct user_name_t user_name; -+ int ccode = 0; -+ int curr_uid; -+ int init = 1; -+ int max_uid = 0; -+ -+ curr_uid = user_id ? user_id : 1; -+ do { -+ memset(&user_access, 0, sizeof(user_access)); -+ user_access.channel = channel; -+ user_access.user_id = curr_uid; -+ ccode = _ipmi_get_user_access(intf, &user_access); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Get User Access (channel %d id %d)", -+ channel, curr_uid); -+ return (-1); - } - -+ memset(&user_name, 0, sizeof(user_name)); -+ user_name.user_id = curr_uid; -+ ccode = _ipmi_get_user_name(intf, &user_name); -+ if (ccode == 0xCC) { -+ user_name.user_id = curr_uid; -+ memset(&user_name.user_name, '\0', 17); -+ } else if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Unable to Get User Name (id %d)", curr_uid); -+ return (-1); -+ } - if (init) { - printf("Maximum User IDs : %d\n", user_access.max_user_ids); - printf("Enabled User IDs : %d\n", user_access.enabled_user_ids); -@@ -416,7 +723,7 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) - - printf("\n"); - printf("User ID : %d\n", curr_uid); -- printf("User Name : %s\n", rsp->data); -+ printf("User Name : %s\n", user_name.user_name); - printf("Fixed Name : %s\n", - (curr_uid <= user_access.fixed_user_ids) ? "Yes" : "No"); - printf("Access Available : %s\n", -@@ -429,475 +736,196 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) - val2str(user_access.privilege_limit, ipmi_privlvl_vals)); - - curr_uid ++; -- -- } while (!userid && curr_uid <= max_uid); -+ } while (!user_id && curr_uid <= max_uid); - - return 0; - } - --static int --ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv) -+/* ipmi_set_user_access - Query BMC for current Channel ACLs, parse CLI args -+ * and update current ACLs. -+ * -+ * returns - 0 on success, (-1) on error -+ */ -+int -+ipmi_set_user_access(struct ipmi_intf *intf, int argc, char **argv) - { -- uint8_t channel, privilege_limit, userid; -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t rqdata[2]; -- struct get_user_access_rsp user_access; -- struct set_user_access_data set_access; -- int i; -- -- if ((argc < 3) || (strncmp(argv[0], "help", 4) == 0)) { -+ struct user_access_t user_access = {0}; -+ int ccode = 0; -+ int i = 0; -+ uint8_t channel = 0; -+ uint8_t priv = 0; -+ uint8_t user_id = 0; -+ if (argc > 0 && strncmp(argv[0], "help", 4) == 0) { - printf_channel_usage(); - return 0; -- } -- -- if (str2uchar(argv[0], &channel) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[0]); -+ } else if (argc < 3) { -+ lprintf(LOG_ERR, "Not enough parameters given."); -+ printf_channel_usage(); - return (-1); - } -- if (str2uchar(argv[1], &userid) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); -+ if (is_ipmi_channel_num(argv[0], &channel) != 0 -+ || is_ipmi_user_id(argv[1], &user_id) != 0) { - return (-1); - } -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = IPMI_GET_USER_ACCESS; -- req.msg.data = rqdata; -- req.msg.data_len = 2; -- -- rqdata[0] = channel & 0xf; -- rqdata[1] = userid & 0x3f; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)", -- rqdata[0], rqdata[1]); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s", -- rqdata[0], rqdata[1], -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ user_access.channel = channel; -+ user_access.user_id = user_id; -+ ccode = _ipmi_get_user_access(intf, &user_access); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Get User Access (channel %d id %d)", -+ channel, user_id); -+ return (-1); - } -- -- memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); -- -- memset(&set_access, 0, sizeof(set_access)); -- set_access.change_bits = 1; -- set_access.callin_callback = user_access.callin_callback; -- set_access.link_auth = user_access.link_auth; -- set_access.ipmi_messaging = user_access.ipmi_messaging; -- set_access.channel = channel; -- set_access.user_id = userid; -- set_access.privilege_limit = user_access.privilege_limit; -- set_access.session_limit = 0; -- -- for (i = 2; i < argc; i ++) -- { -+ for (i = 3; i < argc; i ++) { - if (strncmp(argv[i], "callin=", 7) == 0) { -- set_access.callin_callback = !(strncmp (argv[i]+7, "off", 3)); -- } -- else if (strncmp(argv[i], "link=", 5) == 0) { -- set_access.link_auth = strncmp (argv[i]+5, "off", 3); -- } -- else if (strncmp(argv[i], "ipmi=", 5) == 0) { -- set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3); -- } -- else if (strncmp(argv[i], "privilege=", 10) == 0) { -- if (str2uchar(argv[i]+10, &privilege_limit) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[i]+10); -- return (-1); -+ if (strncmp(argv[i] + 7, "off", 3) == 0) { -+ user_access.callin_callback = 1; -+ } else { -+ user_access.callin_callback = 0; - } -- set_access.privilege_limit = privilege_limit; -- } -- else { -- printf ("Invalid option: %s\n", argv [i]); -- return -1; -- } -- } -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = IPMI_SET_USER_ACCESS; -- req.msg.data = (uint8_t *) &set_access; -- req.msg.data_len = 4; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set User Access (channel %d id %d)", -- set_access.channel, set_access.user_id); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set User Access (channel %d id %d) failed: %s", -- set_access.channel, set_access.user_id, -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -- -- return 0; --} -- -- --static const char * --iana_string(uint32_t iana) --{ -- static char s[10]; -- -- if (iana) -- { -- sprintf(s, "%06x", iana); -- return s; -- } -- else -- return "N/A"; --} -- -- --static int --ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, -- const char * payload_type, -- uint8_t channel) --{ -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- -- uint8_t oem_record; -- uint8_t rqdata[3]; -- uint32_t iana; -- uint8_t auth_alg, integrity_alg, crypt_alg; -- uint8_t cipher_suite_id; -- uint8_t list_index = 0; -- uint8_t cipher_suite_data[1024]; // 0x40 sets * 16 bytes per set -- uint16_t offset = 0; -- uint16_t cipher_suite_data_length = 0; // how much was returned, total -- -- memset(cipher_suite_data, 0, sizeof(cipher_suite_data)); -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; // 0x06 -- req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; // 0x54 -- req.msg.data = rqdata; -- req.msg.data_len = 3; -- -- rqdata[0] = channel; -- rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1); -- rqdata[2] = 0x80; // Always ask for cipher suite format -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -- -- -- // Grab the returned channel number once. We assume it's the same -- // in future calls. -- if (rsp->data_len >= 1) -- channel = rsp->data[0]; -- -- while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) -- { -- // -- // We got back cipher suite data -- store it. -- //printf("copying data to offset %d\n", offset); -- //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); -- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); -- offset += rsp->data_len - 1; -- -- // -- // Increment our list for the next call -- // -- ++list_index; -- rqdata[2] = (rqdata[2] & 0x80) + list_index; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -- } -- -- /* Copy last chunk */ -- if(rsp->data_len > 1) -- { -- // -- // We got back cipher suite data -- store it. -- //printf("copying data to offset %d\n", offset); -- //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); -- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); -- offset += rsp->data_len - 1; -- } -- -- // -- // We can chomp on all our data now. -- // -- cipher_suite_data_length = offset; -- offset = 0; -- -- if (! csv_output) -- printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n"); -- -- while (offset < cipher_suite_data_length) -- { -- if (cipher_suite_data[offset++] == 0xC0) -- { -- oem_record = 0; // standard type -- iana = 0; -- -- // Verify that we have at least a full record left -- if ((cipher_suite_data_length - offset) < 4) // id + 3 algs -- { -- lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); -- return -1; -+ } else if (strncmp(argv[i], "link=", 5) == 0) { -+ if (strncmp(argv[i] + 5, "off", 3) == 0) { -+ user_access.link_auth = 0; -+ } else { -+ user_access.link_auth = 1; - } -- -- cipher_suite_id = cipher_suite_data[offset++]; -- -- } -- else if (cipher_suite_data[offset++] == 0xC1) -- { -- oem_record = 1; // OEM record type -- -- // Verify that we have at least a full record left -- if ((cipher_suite_data_length - offset) < 4) // id + iana + 3 algs -- { -- lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); -- return -1; -+ } else if (strncmp(argv[i], "ipmi=", 5) == 0) { -+ if (strncmp(argv[i] + 5, "off", 3) == 0) { -+ user_access.ipmi_messaging = 0; -+ } else { -+ user_access.ipmi_messaging = 1; - } -- -- cipher_suite_id = cipher_suite_data[offset++]; -- -- // -- // Grab the IANA -- // -- iana = -- cipher_suite_data[offset] | -- (cipher_suite_data[offset + 1] << 8) | -- (cipher_suite_data[offset + 2] << 16); -- offset += 3; -- } -- else -- { -- lprintf(LOG_ERR, "Bad start of record byte in cipher suite data"); -- return -1; -- } -- -- // -- // Grab the algorithms for this cipher suite. I guess we can't be -- // sure of what order they'll come in. Also, I suppose we default -- // to the NONE algorithm if one were absent. This part of the spec is -- // poorly written -- I have read the errata document. For now, I'm only -- // allowing one algorithm per type (auth, integrity, crypt) because I -- // don't I understand how it could be otherwise. -- // -- auth_alg = IPMI_AUTH_RAKP_NONE; -- integrity_alg = IPMI_INTEGRITY_NONE; -- crypt_alg = IPMI_CRYPT_NONE; -- -- while (((cipher_suite_data[offset] & 0xC0) != 0xC0) && -- ((cipher_suite_data_length - offset) > 0)) -- { -- switch (cipher_suite_data[offset] & 0xC0) -- { -- case 0x00: -- // Authentication algorithm specifier -- auth_alg = cipher_suite_data[offset++] & 0x3F; -- break; -- case 0x40: -- // Interity algorithm specifier -- integrity_alg = cipher_suite_data[offset++] & 0x3F; -- break; -- case 0x80: -- // Confidentiality algorithm specifier -- crypt_alg = cipher_suite_data[offset++] & 0x3F; -- break; -+ } else if (strncmp(argv[i], "privilege=", 10) == 0) { -+ if (str2uchar(argv[i] + 10, &priv) != 0) { -+ lprintf(LOG_ERR, -+ "Numeric value expected, but '%s' given.", -+ argv[i] + 10); -+ return (-1); - } -+ user_access.privilege_limit = priv; -+ } else { -+ lprintf(LOG_ERR, "Invalid option: %s\n", argv[i]); -+ return (-1); - } -- -- -- // -- // We have everything we need to spit out a cipher suite record -- // -- printf((csv_output? "%d,%s,%s,%s,%s\n" : -- "%-4d %-7s %-15s %-15s %-15s\n"), -- cipher_suite_id, -- iana_string(iana), -- val2str(auth_alg, ipmi_auth_algorithms), -- val2str(integrity_alg, ipmi_integrity_algorithms), -- val2str(crypt_alg, ipmi_encryption_algorithms)); - } -- -- -- return 0; --} -- -- -- --uint8_t --ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel) --{ -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- struct get_channel_info_rsp info; -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = IPMI_GET_CHANNEL_INFO; -- req.msg.data = &channel; -- req.msg.data_len = 1; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Get Channel Info command failed"); -- return 0; -- } -- if (rsp->ccode > 0) { -- if (rsp->ccode == 0xcc) -- return IPMI_CHANNEL_MEDIUM_RESERVED; -- lprintf(LOG_INFO, "Get Channel Info command failed: %s", -- val2str(rsp->ccode, completion_code_vals)); -- return IPMI_CHANNEL_MEDIUM_RESERVED; -+ ccode = _ipmi_set_user_access(intf, &user_access, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Set User Access (channel %d id %d)", -+ channel, user_id); -+ return (-1); - } -- -- memcpy(&info, rsp->data, sizeof(struct get_channel_info_rsp)); -- -- lprintf(LOG_DEBUG, "Channel type: %s", -- val2str(info.channel_medium, ipmi_channel_medium_vals)); -- -- return info.channel_medium; --} -- --uint8_t --ipmi_current_channel_medium(struct ipmi_intf * intf) --{ -- return ipmi_get_channel_medium(intf, 0xE); --} -- --void --printf_channel_usage() --{ -- lprintf(LOG_NOTICE, "Channel Commands: authcap "); -- lprintf(LOG_NOTICE, " getaccess [user id]"); -- lprintf(LOG_NOTICE, " setaccess " -- " [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]"); -- lprintf(LOG_NOTICE, " info [channel number]"); -- lprintf(LOG_NOTICE, " getciphers [channel]\n"); -- lprintf(LOG_NOTICE, "Possible privilege levels are:"); -- lprintf(LOG_NOTICE, " 1 Callback level"); -- lprintf(LOG_NOTICE, " 2 User level"); -- lprintf(LOG_NOTICE, " 3 Operator level"); -- lprintf(LOG_NOTICE, " 4 Administrator level"); -- lprintf(LOG_NOTICE, " 5 OEM Proprietary level"); -- lprintf(LOG_NOTICE, " 15 No access"); -+ printf("Set User Access (channel %d id %d) successful.\n", -+ channel, user_id); -+ return 0; - } - -- - int --ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv) -+ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) - { - int retval = 0; -- uint8_t channel, priv = 0; -- -- if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) -- { -+ uint8_t channel; -+ uint8_t priv = 0; -+ if (argc < 1) { -+ lprintf(LOG_ERR, "Not enough parameters given."); - printf_channel_usage(); -- } -- else if (strncmp(argv[0], "authcap", 7) == 0) -- { -+ return (-1); -+ } else if (strncmp(argv[0], "help", 4) == 0) { -+ printf_channel_usage(); -+ return 0; -+ } else if (strncmp(argv[0], "authcap", 7) == 0) { - if (argc != 3) { - printf_channel_usage(); - return (-1); -- } else { -- if (str2uchar(argv[1], &channel) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); -- return (-1); -- } -- if (str2uchar(argv[2], &priv) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); -- return (-1); -- } -- retval = ipmi_get_channel_auth_cap(intf, channel, priv); - } -- } -- else if (strncmp(argv[0], "getaccess", 10) == 0) -- { -- if ((argc < 2) || (argc > 3)) -+ if (is_ipmi_channel_num(argv[1], &channel) != 0 -+ || is_ipmi_user_priv_limit(argv[2], &priv) != 0) { -+ return (-1); -+ } -+ retval = ipmi_get_channel_auth_cap(intf, channel, priv); -+ } else if (strncmp(argv[0], "getaccess", 10) == 0) { -+ uint8_t user_id = 0; -+ if ((argc < 2) || (argc > 3)) { -+ lprintf(LOG_ERR, "Not enough parameters given."); - printf_channel_usage(); -- else { -- uint8_t ch = 0; -- uint8_t id = 0; -- if (str2uchar(argv[1], &ch) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); -+ return (-1); -+ } -+ if (is_ipmi_channel_num(argv[1], &channel) != 0) { -+ return (-1); -+ } -+ if (argc == 3) { -+ if (is_ipmi_user_id(argv[2], &user_id) != 0) { - return (-1); - } -- if (argc == 3) { -- if (str2uchar(argv[2], &id) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); -- return (-1); -- } -- } -- retval = ipmi_get_user_access(intf, ch, id); - } -- } -- else if (strncmp(argv[0], "setaccess", 9) == 0) -- { -- retval = ipmi_set_user_access(intf, argc-1, &(argv[1])); -- } -- else if (strncmp(argv[0], "info", 4) == 0) -- { -- if (argc > 2) -+ retval = ipmi_get_user_access(intf, channel, user_id); -+ } else if (strncmp(argv[0], "setaccess", 9) == 0) { -+ return ipmi_set_user_access(intf, (argc - 1), &(argv[1])); -+ } else if (strncmp(argv[0], "info", 4) == 0) { -+ channel = 0xE; -+ if (argc > 2) { - printf_channel_usage(); -- else { -- uint8_t ch = 0xe; -- if (argc == 2) { -- if (str2uchar(argv[1], &ch) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); -- return (-1); -- } -+ return (-1); -+ } -+ if (argc == 2) { -+ if (is_ipmi_channel_num(argv[1], &channel) != 0) { -+ return (-1); - } -- retval = ipmi_get_channel_info(intf, ch); - } -- } -- -- // it channel getciphers [channel] -- else if (strncmp(argv[0], "getciphers", 10) == 0) -- { -- if ((argc < 2) || (argc > 3) || -- (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3))) -+ retval = ipmi_get_channel_info(intf, channel); -+ } else if (strncmp(argv[0], "getciphers", 10) == 0) { -+ /* channel getciphers [channel] */ -+ channel = 0xE; -+ if ((argc < 2) || (argc > 3) || -+ (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3))) { - printf_channel_usage(); -- else -- { -- uint8_t ch = 0xe; -- if (argc == 3) { -- if (str2uchar(argv[2], &ch) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); -- return (-1); -- } -+ return (-1); -+ } -+ if (argc == 3) { -+ if (is_ipmi_channel_num(argv[1], &channel) != 0) { -+ return (-1); - } -- retval = ipmi_get_channel_cipher_suites(intf, -- argv[1], // ipmi | sol -- ch); - } -- } -- else -- { -- printf("Invalid CHANNEL command: %s\n", argv[0]); -+ retval = ipmi_get_channel_cipher_suites(intf, -+ argv[1], /* ipmi | sol */ -+ channel); -+ } else { -+ lprintf(LOG_ERR, "Invalid CHANNEL command: %s\n", argv[0]); - printf_channel_usage(); - retval = -1; - } -- - return retval; - } -+ -+/* printf_channel_usage - print-out help. */ -+void -+printf_channel_usage() -+{ -+ lprintf(LOG_NOTICE, -+"Channel Commands: authcap "); -+ lprintf(LOG_NOTICE, -+" getaccess [user id]"); -+ lprintf(LOG_NOTICE, -+" setaccess " -+" [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]"); -+ lprintf(LOG_NOTICE, -+" info [channel number]"); -+ lprintf(LOG_NOTICE, -+" getciphers [channel]"); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"Possible privilege levels are:"); -+ lprintf(LOG_NOTICE, -+" 1 Callback level"); -+ lprintf(LOG_NOTICE, -+" 2 User level"); -+ lprintf(LOG_NOTICE, -+" 3 Operator level"); -+ lprintf(LOG_NOTICE, -+" 4 Administrator level"); -+ lprintf(LOG_NOTICE, -+" 5 OEM Proprietary level"); -+ lprintf(LOG_NOTICE, -+" 15 No access"); -+} -diff --git a/lib/ipmi_dcmi.c b/lib/ipmi_dcmi.c -index 6e030f9..aeee944 100755 ---- a/lib/ipmi_dcmi.c -+++ b/lib/ipmi_dcmi.c -@@ -62,7 +62,7 @@ - #define IPMI_LAN_PORT 0x26f - - extern int verbose; -- -+extern int csv_output; - static int ipmi_print_sensor_info(struct ipmi_intf *intf, uint16_t rec_id); - - /******************************************************************************* -@@ -295,6 +295,228 @@ const struct valstr dcmi_ccode_vals[] = { - { 0xFF, NULL } - }; - -+/* -+ * Start of Node Manager Operations -+ */ -+ -+const struct dcmi_cmd dcmi_sampling_vals[] = { -+ { 0x05, "5_sec", "" }, -+ { 0x0f, "15_sec", "" }, -+ { 0x1E, "30_sec", "" }, -+ { 0x41, "1_min", "" }, -+ { 0x43, "3_min", "" }, -+ { 0x47, "7_min", "" }, -+ { 0x4F, "15_min", "" }, -+ { 0x5E, "30_min", "" }, -+ { 0x81, "1_hour", ""}, -+ { 0x00, NULL, NULL }, -+}; -+ -+/* Primary Node Manager commands */ -+const struct dcmi_cmd nm_cmd_vals[] = { -+ { 0x00, "discover", "Discover Node Manager " }, -+ { 0x01, "capability", "Get Node Manager Capabilities" }, -+ { 0x02, "control", "Enable/Disable Policy Control" }, -+ { 0x03, "policy", "Add/Remove Policies" }, -+ { 0x04, "statistics", "Get Statistics" }, -+ { 0x05, "power", "Set Power Draw Range" }, -+ { 0x06, "suspend", "Set/Get Policy suspend periods" }, -+ { 0x07, "reset", "Reset Statistics" }, -+ { 0x08, "alert", "Set/Get/Clear Alert destination" }, -+ { 0x09, "threshold", "Set/Get Alert Thresholds" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_ctl_cmds[] = { -+ { 0x01, "enable", " " }, -+ { 0x00, "disable", ""}, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_ctl_domain[] = { -+ { 0x00, "global", "" }, -+ { 0x02, "per_domain", " (default is platform)" }, -+ { 0x04, "per_policy", "<0-7>" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+/* Node Manager Domain codes */ -+const struct dcmi_cmd nm_domain_vals[] = { -+ { 0x00, "platform", "" }, -+ { 0x01, "CPU", "" }, -+ { 0x02, "Memory", "" }, -+ { 0x03, "protection", "" }, -+ { 0x04, "I/O", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_version_vals[] = { -+ { 0x01, "1.0", "" }, -+ { 0x02, "1.5", "" }, -+ { 0x03, "2.0", "" }, -+ { 0x04, "2.5", "" }, -+ { 0x05, "3.0", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_capability_opts[] = { -+ { 0x01, "domain", " (default is platform)" }, -+ { 0x02, "inlet", "Inlet temp trigger" }, -+ { 0x03, "missing", "Missing Power reading trigger" }, -+ { 0x04, "reset", "Time after Host reset trigger" }, -+ { 0x05, "boot", "Boot time policy" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_policy_type_vals[] = { -+ { 0x00, "No trigger, use Power Limit", "" }, -+ { 0x01, "Inlet temp trigger", "" }, -+ { 0x02, "Missing Power reading trigger", "" }, -+ { 0x03, "Time after Host reset trigger", "" }, -+ { 0x04, "number of cores to disable at boot time", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_stats_opts[] = { -+ { 0x01, "domain", " (default is platform)" }, -+ { 0x02, "policy_id", "<0-7>" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_stats_mode[] = { -+ { 0x01, "power", "global power" }, -+ { 0x02, "temps", "inlet temperature" }, -+ { 0x11, "policy_power", "per policy power" }, -+ { 0x12, "policy_temps", "per policy inlet temp" }, -+ { 0x13, "policy_throt", "per policy throttling stats" }, -+ { 0x1B, "requests", "unhandled requests" }, -+ { 0x1C, "response", "response time" }, -+ { 0x1D, "cpu_throttling", "CPU throttling" }, -+ { 0x1E, "mem_throttling", "memory throttling" }, -+ { 0x1F, "comm_fail", "host communication failures" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_policy_action[] = { -+ { 0x00, "get", "nm policy get policy_id <0-7> [domain ]" }, -+ { 0x04, "add", "nm policy add policy_id <0-7> [domain ] correction auto|soft|hard power |inlet trig_lim stats enable|disable" }, -+ { 0x05, "remove", "nm policy remove policy_id <0-7> [domain ]" }, -+ { 0x06, "limiting", "nm policy limiting [domain ]" }, -+ { 0xFF, NULL, NULL }, -+}; -+const struct dcmi_cmd nm_policy_options[] = { -+ { 0x01, "enable", "" }, -+ { 0x02, "disable", "" }, -+ { 0x03, "domain", "" }, -+ { 0x04, "inlet", "inlet air temp full limiting (SCRAM)"}, -+ { 0x06, "correction", "auto, soft, hard" }, -+ { 0x08, "power", "power limit in watts" }, -+ { 0x09, "trig_lim", "time to send alert" }, -+ { 0x0A, "stats", "moving window averaging time" }, -+ { 0x0B, "policy_id", "policy number" }, -+ { 0x0C, "volatile", "save policy in volatiel memory" }, -+ { 0x0D, "cores_off", "at boot time, disable N cores" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+/* if "trigger" command used from nm_policy_options */ -+const struct dcmi_cmd nm_trigger[] = { -+ { 0x00, "none", "" }, -+ { 0x01, "temp", "" }, -+ { 0x02, "reset", "" }, -+ { 0x03, "boot", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+/* if "correction" used from nm_policy_options */ -+const struct dcmi_cmd nm_correction[] = { -+ { 0x00, "auto", "" }, -+ { 0x01, "soft", "" }, -+ { 0x02, "hard", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+/* returned codes from get policy */ -+const struct dcmi_cmd nm_correction_vals[] = { -+ { 0x00, "no T-state use", "" }, -+ { 0x01, "no T-state use", "" }, -+ { 0x02, "use T-states", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+/* if "exception" used from nm_policy_options */ -+const struct dcmi_cmd nm_exception[] = { -+ { 0x00, "none", "" }, -+ { 0x01, "alert", "" }, -+ { 0x02, "shutdown", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_reset_mode[] = { -+ { 0x00, "global", "" }, -+ { 0x01, "per_policy", "" }, -+ { 0x1B, "requests", "" }, -+ { 0x1C, "response", "" }, -+ { 0x1D, "throttling", "" }, -+ { 0x1E, "memory", "", }, -+ { 0x1F, "comm", "" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_power_range[] = { -+ { 0x01, "domain", "domain (default is platform)" }, -+ { 0x02, "min", " min " }, -+ { 0x03, "max", "max " }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_alert_opts[] = { -+ { 0x01, "set", "nm alert set chan dest string " }, -+ { 0x02, "get", "nm alert get" }, -+ { 0x03, "clear", "nm alert clear dest " }, -+}; -+ -+const struct dcmi_cmd nm_set_alert_param[] = { -+ { 0x01, "chan", "chan " }, -+ { 0x02, "dest", "dest " }, -+ { 0x03, "string", "string " }, -+}; -+ -+const struct dcmi_cmd nm_thresh_cmds[] = { -+ { 0x01, "set", "nm thresh set [domain ] policy_id thresh_array" }, -+ { 0x02, "get", "nm thresh get [domain ] policy_id " }, -+}; -+ -+const struct dcmi_cmd nm_thresh_param[] = { -+ { 0x01, "domain", " (default is platform)" }, -+ { 0x02, "policy_id", "<0-7>" }, -+ { 0xFF, NULL, NULL }, -+}; -+ -+const struct dcmi_cmd nm_suspend_cmds[] = { -+ { 0x01, "set", "nm suspend set [domain policy_id " }, -+ { 0x02, "get", "nm suspend get [domain policy_id " }, -+}; -+ -+const struct valstr nm_ccode_vals[] = { -+ { 0x80, "Policy ID Invalid"}, -+ { 0x81, "Domain ID Invalid"}, -+ { 0x82, "Unknown policy trigger type"}, -+ { 0x84, "Power Limit out of range"}, -+ { 0x85, "Correction Time out of range"}, -+ { 0x86, "Policy Trigger value out of range"}, -+ { 0x88, "Invalid Mode"}, -+ { 0x89, "Statistics Reporting Period out of range"}, -+ { 0x8B, "Invalid value for Aggressive CPU correction field"}, -+ { 0xA1, "No policy is currently limiting for the specified domain ID"}, -+ { 0xC4, "No space available"}, -+ { 0xD4, "Insufficient privledge level due wrong responder LUN"}, -+ { 0xD5, "Policy exists and param unchangeable while enabled"}, -+ { 0xD6, "Command subfunction disabled or unavailable"}, -+ { 0xFF, NULL }, -+}; -+ -+ - /* End strings */ - - /* This was taken from print_valstr() from helper.c. It serves the same -@@ -400,7 +622,7 @@ val2str2(uint16_t val, const struct dcmi_cmd *vs) - if (vs[i].val == val) - return vs[i].str; - } -- memset(un_str, 0, 32); -+ memset(un_str, 0, sizeof (un_str)); - snprintf(un_str, 32, "Unknown (0x%x)", val); - return un_str; - } -@@ -439,6 +661,40 @@ chk_rsp(struct ipmi_rs * rsp) - return 0; - } - -+/* check the Node Manager response from the BMC -+ * @rsp: Response data structure -+ */ -+static int -+chk_nm_rsp(struct ipmi_rs * rsp) -+{ -+ /* if the response from the intf is NULL then the BMC is experiencing -+ * some issue and cannot complete the command -+ */ -+ if (rsp == NULL) { -+ lprintf(LOG_ERR, "\n No reponse to NM request"); -+ return 1; -+ } -+ /* if the completion code is greater than zero there was an error. We'll -+ * use val2str from helper.c to print the error from either the DCMI -+ * completion code struct or the generic IPMI completion_code_vals struct -+ */ -+ if ((rsp->ccode >= 0x80) && (rsp->ccode <= 0xD6)) { -+ lprintf(LOG_ERR, "\n NM request failed because: %s (%x)", -+ val2str(rsp->ccode, nm_ccode_vals), rsp->ccode); -+ return 1; -+ } else if (rsp->ccode > 0) { -+ lprintf(LOG_ERR, "\n NM request failed because: %s (%x)", -+ val2str(rsp->ccode, completion_code_vals), rsp->ccode); -+ return 1; -+ } -+ /* check to make sure this is a DCMI firmware */ -+ if(rsp->data[0] != 0x57) { -+ printf("\n A valid NM command was not returned! (%x)", rsp->data[0]); -+ return 1; -+ } -+ return 0; -+} -+ - /* Get capabilities ipmi response - * - * This function returns the available capabilities of the platform. -@@ -494,8 +750,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf) - "DCMI Discovery is available only when LANplus(IPMI v2.0) is enabled."); - return (-1); - # else -- int rc; -- struct ipmi_session *s; -+ struct ipmi_session_params *p; - - if (intf->opened == 0 && intf->open != NULL) { - if (intf->open(intf) < 0) -@@ -504,18 +759,18 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf) - if (intf == NULL || intf->session == NULL) - return -1; - -- s = intf->session; -+ p = &intf->ssn_params; - -- if (s->port == 0) -- s->port = IPMI_LAN_PORT; -- if (s->privlvl == 0) -- s->privlvl = IPMI_SESSION_PRIV_ADMIN; -- if (s->timeout == 0) -- s->timeout = IPMI_LAN_TIMEOUT; -- if (s->retry == 0) -- s->retry = IPMI_LAN_RETRY; -+ if (p->port == 0) -+ p->port = IPMI_LAN_PORT; -+ if (p->privlvl == 0) -+ p->privlvl = IPMI_SESSION_PRIV_ADMIN; -+ if (p->timeout == 0) -+ p->timeout = IPMI_LAN_TIMEOUT; -+ if (p->retry == 0) -+ p->retry = IPMI_LAN_RETRY; - -- if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) { -+ if (p->hostname == NULL || strlen((const char *)p->hostname) == 0) { - lprintf(LOG_ERR, "No hostname specified!"); - return -1; - } -@@ -530,7 +785,7 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf) - - if (intf->fd < 0) { - lperror(LOG_ERR, "Connect to %s failed", -- s->hostname); -+ p->hostname); - intf->close(intf); - return -1; - } -@@ -552,17 +807,18 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf) - static int - ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf, uint8_t selector) - { -- uint8_t i; -- uint8_t bit_shifter = 0; - struct capabilities cape; - struct ipmi_rs * rsp; -+ uint8_t reply[16]; - rsp = ipmi_dcmi_getcapabilities(intf, selector); -+ int j; - - if(chk_rsp(rsp)) - return -1; - - /* if there were no errors, the command worked! */ - memcpy(&cape, rsp->data, sizeof (cape)); -+ memcpy(&reply, rsp->data, sizeof (reply)); - /* check to make sure that this is a 1.0/1.1/1.5 command */ - if ((cape.conformance != IPMI_DCMI_CONFORM) - && (cape.conformance != IPMI_DCMI_1_1_CONFORM) -@@ -680,6 +936,16 @@ ipmi_dcmi_prnt_getcapabilities(struct ipmi_intf * intf, uint8_t selector) - cape.data_byte3); - } - break; -+ case 0x05: -+ /* Node Manager */ -+ printf("\n Node Manager Get DCMI Capability Info: \n"); -+ printf(" DCMI Specification %d.%d\n", reply[1], reply[2]); -+ printf(" Rolling average time period options: %d\n", reply[4]); -+ printf(" Sample time options: "); -+ for (j = 1; dcmi_sampling_vals[j-1].str != NULL; j++) -+ printf(" %s ", val2str2(reply[4+j],dcmi_sampling_vals)); -+ printf("\n"); -+ break; - default: - return -1; - } -@@ -728,7 +994,6 @@ ipmi_dcmi_getassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length) - static int - ipmi_dcmi_prnt_getassettag(struct ipmi_intf * intf) - { -- uint8_t data_byte2; - struct ipmi_rs * rsp; /* ipmi response */ - uint8_t taglength = 0; - uint8_t getlength = 0; -@@ -800,16 +1065,15 @@ ipmi_dcmi_setassettag(struct ipmi_intf * intf, uint8_t offset, uint8_t length, - static int - ipmi_dcmi_prnt_setassettag(struct ipmi_intf * intf, uint8_t * data) - { -- uint8_t data_byte2; - struct ipmi_rs * rsp; /* ipmi response */ - uint8_t tmpData[DCMI_MAX_BYTE_SIZE]; -- uint8_t taglength = 0; -+ int32_t taglength = 0; - uint8_t getlength = 0; - uint8_t offset = 0; - uint8_t i; - - /* now let's get the asset tag length */ -- taglength = strlen(data); -+ taglength = strlen((char *)data); - if (taglength > 64){ - lprintf(LOG_ERR, "\nValue is too long."); - return -1; -@@ -864,7 +1128,6 @@ ipmi_dcmi_getmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length) - static int - ipmi_dcmi_prnt_getmngctrlids(struct ipmi_intf * intf) - { -- uint8_t data_byte2; - struct ipmi_rs * rsp; /* ipmi response */ - uint8_t taglength = 0; - uint8_t getlength = 0; -@@ -942,7 +1205,6 @@ ipmi_dcmi_setmngctrlids(struct ipmi_intf * intf, uint8_t offset, uint8_t length, - static int - ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf, uint8_t * data) - { -- uint8_t data_byte2; - struct ipmi_rs * rsp; /* ipmi response */ - uint8_t tmpData[DCMI_MAX_BYTE_SIZE]; - uint8_t taglength = 0; -@@ -951,7 +1213,7 @@ ipmi_dcmi_prnt_setmngctrlids(struct ipmi_intf * intf, uint8_t * data) - uint8_t i; - - data += '\0'; -- taglength = strlen(data) +1; -+ taglength = strlen((char *)data) +1; - - if (taglength > 64) { - lprintf(LOG_ERR, "\nValue is too long."); -@@ -1048,7 +1310,7 @@ ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr) - /* cache the data since it may be destroyed by subsequent - * ipmi_xxx calls - */ -- memcpy(id_buff, &rsp->data[3], 16); -+ memcpy(id_buff, &rsp->data[3], sizeof (id_buff)); - for (i=0; idata so that we only care about bit 6 */ - if((val.state & 0x40) == 0x40) { -@@ -1496,7 +1766,6 @@ ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf, const char * option, - struct power_limit val; - uint8_t msg_data[15]; /* number of request data bytes */ - uint32_t lvalue = 0; -- int i; - - rsp = ipmi_dcmi_pwr_glimit(intf); /* get the power limit settings */ - # if 0 -@@ -1674,7 +1943,7 @@ ipmi_dcmi_pwr_slimit(struct ipmi_intf * intf, const char * option, - */ - msg_data[11] = 0x00; /* reserved */ - msg_data[12] = 0x00; /* reserved */ -- /* fill msg_data[7] with the first 16 bits of val.sample */ -+ /* fill msg_data[13] with the first 16 bits of val.sample */ - *(uint16_t*)(&msg_data[13]) = val.sample; - /* msg_data[13] = 0x03; */ - memset(&req, 0, sizeof(req)); -@@ -1731,349 +2000,1699 @@ ipmi_dcmi_pwr_actdeact(struct ipmi_intf * intf, uint8_t option) - } - /* end power management activate/deactivate */ - --/* main -+/* Node Manager discover */ -+static int -+_ipmi_nm_discover(struct ipmi_intf * intf, struct nm_discover *disc) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_VERSION; -+ req.msg.data = msg_data; -+ req.msg.data_len = 3; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ memcpy(disc, rsp->data, sizeof (struct nm_discover)); -+ return 0; -+} -+/* Get NM capabilities - * -- * @intf: dcmi interface handler -- * @argc: argument count -- * @argv: argument vector -+ * This function returns the available capabilities of the platform. -+ * -+ * returns success/failure -+ * -+ * @intf: ipmi interface handler -+ * @caps: fills in capability struct - */ --int --ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) -+static int -+_ipmi_nm_getcapabilities(struct ipmi_intf * intf, uint8_t domain, uint8_t trigger, struct nm_capability *caps) - { -- int rc = 0; -- uint8_t ctl = 0; -- int i, ii, instances; -+ struct ipmi_rq req; /* request data to send to the BMC */ - struct ipmi_rs *rsp; -+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */ - -- if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) { -- print_strs(dcmi_cmd_vals, -- "Data Center Management Interface commands", -- -1, 0); -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ msg_data[4] = trigger; /* power control policy or trigger */ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_CAP; -+ req.msg.data = msg_data; -+ req.msg.data_len = 5; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { - return -1; - } -- /* start the cmd requested */ -- switch (str2val2(argv[0], dcmi_cmd_vals)) { -- case 0x00: -- /* discover capabilities*/ -- for (i = 1; dcmi_capable_vals[i-1].str != NULL; i++) { -- if (ipmi_dcmi_prnt_getcapabilities(intf, i) < 0) { -- printf("Error discovering %s capabilities!\n", -- val2str2(i, dcmi_capable_vals)); -- return -1; -- } -- } -- break; -- case 0x01: -- /* power */ -- argv++; -- if (argv[0] == NULL) { -- print_strs(dcmi_pwrmgmt_vals, "power ", -- -1, 0); -- return -1; -- } -- /* power management */ -- switch (str2val2(argv[0], dcmi_pwrmgmt_vals)) { -- case 0x00: -- /* get reading */ -- rc = ipmi_dcmi_pwr_rd(intf); -- break; -- case 0x01: -- /* get limit */ -- /* because the get limit function is also used to -- * populate unchanged values for the set limit -- * command it returns an ipmi response structure -- */ -- rc = ipmi_dcmi_pwr_prnt_glimit(intf); -- break; -- case 0x02: -- /* set limit */ -- if (argc < 4) { -- print_strs(dcmi_pwrmgmt_set_usage_vals, -- "set_limit ", -- -1, 0); -- return -1; -- } -- if ( argc == 10) { -- /* Let`s initialize dcmi power parameters */ -- struct ipmi_rq req; -- uint8_t data[256]; -- uint16_t sample = 0; -- uint16_t limit = 0; -- uint32_t correction = 0; -- -- memset(data, 0, sizeof(data)); -- memset(&req, 0, sizeof(req)); -- -- req.msg.netfn = IPMI_NETFN_DCGRP; -- req.msg.lun = 0x00; -- req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */ -- req.msg.data = data; /* Contents above */ -- req.msg.data_len = 15; -- -- data[0] = IPMI_DCMI; /* Group Extension Identification */ -- data[1] = 0x0; /* reserved */ -- data[2] = 0x0; /* reserved */ -- data[3] = 0x0; /* reserved */ -- -- /* action */ -- switch (str2val2(argv[2], dcmi_pwrmgmt_action_vals)) { -- case 0x00: -- /* no_action */ -- data[4] = 0x00; -- break; -- case 0x01: -- /* power_off */ -- data[4] = 0x01; -- break; -- case 0x11: -- /* sel_logging*/ -- data[4] = 0x11; -- break; -- case 0xFF: -- /* error - not a string we knew what to do with */ -- lprintf(LOG_ERR, "Given Action '%s' is invalid.", -- argv[2]); -- return -1; -- } -- /* limit */ -- if (str2ushort(argv[4], &limit) != 0) { -- lprintf(LOG_ERR, -- "Given Limit '%s' is invalid.", -- argv[4]); -- return (-1); -- } -- data[5] = limit >> 0; -- data[6] = limit >> 8; -- /* correction */ -- if (str2uint(argv[6], &correction) != 0) { -- lprintf(LOG_ERR, -- "Given Correction '%s' is invalid.", -- argv[6]); -- return (-1); -- } -- data[7] = correction >> 0; -- data[8] = correction >> 8; -- data[9] = correction >> 16; -- data[10] = correction >> 24; -- data[11] = 0x00; /* reserved */ -- data[12] = 0x00; /* reserved */ -- /* sample */ -- if (str2ushort(argv[8], &sample) != 0) { -- lprintf(LOG_ERR, -- "Given Sample '%s' is invalid.", -- argv[8]); -- return (-1); -- } -- data[13] = sample >> 0; -- data[14] = sample >> 8; -+ memcpy(caps, rsp->data, sizeof (struct nm_capability)); -+ return 0; -+} - -- rsp = intf->sendrecv(intf, &req); -- if (chk_rsp(rsp)) { -- return -1; -- } -- } else { -- /* loop through each parameter and value until we have neither */ -- while ((argv[1] != NULL) && (argv[2] != NULL)) { -- rc = ipmi_dcmi_pwr_slimit(intf, argv[1], argv[2]); -- /* catch any error that the set limit function returned */ -- if (rc > 0) { -- print_strs(dcmi_pwrmgmt_set_usage_vals, -- "set_limit ", -1, 0); -- return -1; -- } -- /* the first argument is the command and the second is the -- * value. Move argv two places; what is now 3 will be 1 -- */ -- argv+=2; -- } -- } -- rc = ipmi_dcmi_pwr_prnt_glimit(intf); -- break; -- case 0x03: -- /* activate */ -- rc = ipmi_dcmi_pwr_actdeact(intf, 1); -- break; -- case 0x04: -- /* deactivate */ -- rc = ipmi_dcmi_pwr_actdeact(intf, 0); -- break; -- default: -- /* no valid options */ -- print_strs(dcmi_pwrmgmt_vals, -- "power ", -1, 0); -- break; -- } -- /* power mgmt end */ -- break; -- /* end power command */ -- case 0x02: -- /* sensor print */ -- /* Look for each item in the dcmi_discvry_snsr_vals struct -- * and if it exists, print the sdr record id(s) for it. -- * Use the val from each one as the sensor number. -- */ -- for (i = 0; dcmi_discvry_snsr_vals[i].str != NULL; i++) { -- /* get all of the information about this sensor */ -- rc = ipmi_dcmi_prnt_discvry_snsr(intf, -- dcmi_discvry_snsr_vals[i].val); -- } -- break; -- /* end sensor print */ -- case 0x03: -- /* asset tag */ -- if(ipmi_dcmi_prnt_getassettag(intf) < 0) { -- lprintf(LOG_ERR, "Error getting asset tag!"); -- return -1; -- } -- break; -- /* end asset tag */ -- case 0x04: -- { -- /* set asset tag */ -- if (argc == 1 ) { -- print_strs(dcmi_cmd_vals, -- "Data Center Management Interface commands", -- -1, 0); -- return -1; -- } -- if (ipmi_dcmi_prnt_setassettag(intf, argv[1]) < 0) { -- lprintf(LOG_ERR, "\nError setting asset tag!"); -- return -1; -- } -- break; -+static int -+_ipmi_nm_get_policy(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, struct nm_get_policy *policy) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ msg_data[4] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_POLICY; -+ req.msg.data = msg_data; -+ req.msg.data_len = 5; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; - } -- /* end set asset tag */ -- case 0x05: -- /* get management controller identifier string */ -- if (ipmi_dcmi_prnt_getmngctrlids(intf) < 0) { -- lprintf(LOG_ERR, -- "Error getting management controller identifier string!"); -- return -1; -- } -- break; -- /* end get management controller identifier string */ -- case 0x06: -- { -- /* set management controller identifier string */ -- if (argc == 1 ) { -- print_strs(dcmi_cmd_vals, -- "Data Center Management Interface commands", -- -1, 0); -- return -1; -- } -- if (ipmi_dcmi_prnt_setmngctrlids(intf, argv[1]) < 0) { -- lprintf(LOG_ERR, -- "Error setting management controller identifier string!"); -- return -1; -- } -- break; -+ memcpy(policy, rsp->data, sizeof (struct nm_get_policy)); -+ return 0; -+} -+static int -+_ipmi_nm_set_policy(struct ipmi_intf * intf, struct nm_policy *policy) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_SET_POLICY; -+ req.msg.data = (uint8_t *)policy; -+ req.msg.data_len = sizeof(struct nm_policy); -+ policy->intel_id[0] = 0x57; policy->intel_id[1] =1; policy->intel_id[2] =0; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; - } -- /* end set management controller identifier string */ -- case 0x07: -- { -- uint8_t entityID = 0; -- uint8_t entityInst = 0; -- uint8_t persistanceFlag; -- uint8_t actionHardPowerOff; -- uint8_t actionLogToSEL; -- uint8_t tempLimit = 0; -- uint8_t samplingTimeLSB; -- uint8_t samplingTimeMSB; -- uint16_t samplingTime = 0; -- /* Thermal policy get/set */ -- /* dcmitool dcmi thermalpolicy get */ -- switch (str2val2(argv[1], dcmi_thermalpolicy_vals)) { -- case 0x00: -- if (argc < 4) { -- lprintf(LOG_NOTICE, "Get "); -- return -1; -- } -- if (str2uchar(argv[2], &entityID) != 0) { -- lprintf(LOG_ERR, -- "Given Entity ID '%s' is invalid.", -- argv[2]); -- return (-1); -- } -- if (str2uchar(argv[3], &entityInst) != 0) { -- lprintf(LOG_ERR, -- "Given Instance ID '%s' is invalid.", -- argv[3]); -- return (-1); -- } -- rc = ipmi_dcmi_getthermalpolicy(intf, entityID, entityInst); -- break; -- case 0x01: -- if (argc < 4) { -- lprintf(LOG_NOTICE, "Set "); -- return -1; -- } else if (argc < 9) { -- print_strs(dcmi_thermalpolicy_set_parameters_vals, -- "Set thermalpolicy instance parameters: " -- " " -- " " -- " ", -- -1, 0); -+ return 0; -+} -+ -+static int -+_ipmi_nm_policy_limiting(struct ipmi_intf * intf, uint8_t domain) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[4]; /* 'raw' data to be sent to the BMC */ -+ -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_LIMITING; -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ req.msg.data = msg_data; -+ req.msg.data_len = 4; -+ rsp = intf->sendrecv(intf, &req); -+ /* check for special case error of no policy is limiting */ -+ if (rsp && (rsp->ccode == 0xA1)) -+ return 0x80; -+ else if (chk_nm_rsp(rsp)) -+ return -1; -+ return rsp->data[0]; -+} -+ -+static int -+_ipmi_nm_control(struct ipmi_intf * intf, uint8_t scope, uint8_t domain, uint8_t policy_id) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = scope; -+ msg_data[4] = domain; -+ msg_data[5] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_POLICY_CTL; -+ req.msg.data = msg_data; -+ req.msg.data_len = 6; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+/* Get NM statistics -+ * -+ * This function returns the statistics -+ * -+ * returns success/failure -+ * -+ * @intf: ipmi interface handler -+ * @selector: Parameter selector -+ */ -+static int -+_ipmi_nm_statistics(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id, struct nm_statistics *caps) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = mode; -+ msg_data[4] = domain; -+ msg_data[5] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_STATS; -+ req.msg.data = msg_data; -+ req.msg.data_len = 6; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ memcpy(caps, rsp->data, sizeof (struct nm_statistics)); -+ return 0; -+} -+ -+static int -+_ipmi_nm_reset_stats(struct ipmi_intf * intf, uint8_t mode, uint8_t domain, uint8_t policy_id) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = mode; -+ msg_data[4] = domain; -+ msg_data[5] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_RESET_STATS; -+ req.msg.data = msg_data; -+ req.msg.data_len = 6; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+_nm_set_range(struct ipmi_intf * intf, uint8_t domain, uint16_t minimum, uint16_t maximum) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[8]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ msg_data[4] = minimum & 0xFF; -+ msg_data[5] = minimum >> 8; -+ msg_data[6] = maximum & 0xFF; -+ msg_data[7] = maximum >> 8; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_SET_POWER; -+ req.msg.data = msg_data; -+ req.msg.data_len = 8; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+_ipmi_nm_get_alert(struct ipmi_intf * intf, struct nm_set_alert *alert) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[3]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_ALERT_DS; -+ req.msg.data = msg_data; -+ req.msg.data_len = 3; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ memcpy(alert, rsp->data, sizeof (struct nm_set_alert)); -+ return 0; -+} -+ -+static int -+_ipmi_nm_set_alert(struct ipmi_intf * intf, struct nm_set_alert *alert) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[6]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = alert->chan; -+ msg_data[4] = alert->dest; -+ msg_data[5] = alert->string; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_SET_ALERT_DS; -+ req.msg.data = msg_data; -+ req.msg.data_len = 6; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+/* -+ * -+ * get alert threshold values. -+ * -+ * the list pointer is assumed to point to an array of 16 short integers. -+ * This array is filled in for valid thresholds returned. -+ */ -+static int -+_ipmi_nm_get_thresh(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, uint16_t *list) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */ -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ msg_data[4] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_ALERT_TH; -+ req.msg.data = msg_data; -+ req.msg.data_len = 5; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ if (rsp->data[3] > 0) -+ *list++ = (rsp->data[5] << 8) | rsp->data[4]; -+ if (rsp->data[3] > 1) -+ *list++ = (rsp->data[7] << 8) | rsp->data[6]; -+ if (rsp->data[3] > 2) -+ *list = (rsp->data[9] << 8) | rsp->data[8]; -+ return 0; -+} -+ -+static int -+_ipmi_nm_set_thresh(struct ipmi_intf * intf, struct nm_thresh * thresh) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[IPMI_NM_SET_THRESH_LEN]; /* 'raw' data to be sent to the BMC */ -+ -+ memset(&msg_data, 0, sizeof(msg_data)); -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = thresh->domain; -+ msg_data[4] = thresh->policy_id; -+ msg_data[5] = thresh->count; -+ if (thresh->count > 0) { -+ msg_data[7] = thresh->thresholds[0] >> 8; -+ msg_data[6] = thresh->thresholds[0] & 0xFF; -+ } -+ if (thresh->count > 1) { -+ msg_data[9] = thresh->thresholds[1] >> 8; -+ msg_data[8] = thresh->thresholds[1] & 0xFF; -+ } -+ if (thresh->count > 2) { -+ msg_data[11] = thresh->thresholds[2] >> 8; -+ msg_data[10] = thresh->thresholds[2] & 0xFF; -+ } -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_SET_ALERT_TH; -+ req.msg.data = msg_data; -+ req.msg.data_len = 6 + (thresh->count * 2); -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+/* -+ * -+ * get suspend periods -+ * -+ */ -+static int -+_ipmi_nm_get_suspend(struct ipmi_intf * intf, uint8_t domain, uint8_t policy_id, int *count, struct nm_period *periods) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[5]; /* 'raw' data to be sent to the BMC */ -+ int i; -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = domain; -+ msg_data[4] = policy_id; -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_GET_SUSPEND; -+ req.msg.data = msg_data; -+ req.msg.data_len = 5; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ *count = rsp->data[3]; -+ for (i = 0; i < rsp->data[3]; i += 3, periods++) { -+ periods->start = rsp->data[4+i]; -+ periods->stop = rsp->data[5+i]; -+ periods->repeat = rsp->data[6+i]; -+ } -+ return 0; -+} -+ -+static int -+_ipmi_nm_set_suspend(struct ipmi_intf * intf, struct nm_suspend *suspend) -+{ -+ struct ipmi_rq req; /* request data to send to the BMC */ -+ struct ipmi_rs *rsp; -+ uint8_t msg_data[21]; /* 6 control bytes + 5 suspend periods, 3 bytes per period */ -+ struct nm_period *periods; -+ int i; -+ -+ msg_data[0] = 0x57; -+ msg_data[1] = 1; -+ msg_data[2] = 0; -+ msg_data[3] = suspend->domain; -+ msg_data[4] = suspend->policy_id; -+ msg_data[5] = suspend->count; -+ for (i = 0, periods = &suspend->period[0]; i < (suspend->count*3); i += 3, periods++) { -+ msg_data[6+i] = periods->start; -+ msg_data[7+i] = periods->stop; -+ msg_data[8+i] = periods->repeat; -+ } -+ memset(&req, 0, sizeof(req)); -+ req.msg.data_len = 6 + (suspend->count*3); -+ req.msg.netfn = IPMI_NETFN_OEM; -+ req.msg.cmd = IPMI_NM_SET_SUSPEND; -+ req.msg.data = msg_data; -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_nm_rsp(rsp)) { -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+ipmi_nm_getcapabilities(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t option; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t trigger = 0; /* default power policy (no trigger) */ -+ struct nm_capability caps; -+ -+ while (--argc > 0) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((option = str2val2(argv[0], nm_capability_opts)) == 0xFF) { -+ print_strs(nm_capability_opts, "Capability commands", LOG_ERR, 0); -+ return -1; -+ } -+ switch (option) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ break; -+ case 0x02: /* Inlet */ -+ trigger = 1; -+ break; -+ case 0x03: /* Missing power reading */ -+ trigger = 2; -+ break; -+ case 0x04: /* Time after host reset */ -+ trigger = 3; -+ break; -+ case 0x05: /* Boot time policy */ -+ trigger = 4; -+ break; -+ default: -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ trigger |= 0x10; -+ memset(&caps, 0, sizeof(caps)); -+ if (_ipmi_nm_getcapabilities(intf, domain, trigger, &caps)) -+ return -1; -+ if (csv_output) { -+ printf("%d,%u,%u,%u,%u,%u,%u,%s\n", -+ caps.max_settings, caps.max_value,caps.min_value, -+ caps.min_corr/1000, caps.max_corr/1000, -+ caps.min_stats, caps.max_stats, -+ val2str2(caps.scope&0xF, nm_domain_vals)); -+ return 0; -+ } -+ printf(" power policies:\t\t%d\n", caps.max_settings); -+ switch (trigger&0xF) { -+ case 0: /* power */ -+ printf(" max_power\t\t%7u Watts\n min_power\t\t%7u Watts\n", -+ caps.max_value, caps.min_value); -+ break; -+ case 1: /* Inlet */ -+ printf(" max_temp\t\t%7u C\n min_temp\t\t%7u C\n", -+ caps.max_value, caps.min_value); -+ break; -+ case 2: /* Missing reading time */ -+ case 3: /* Time after host reset */ -+ printf(" max_time\t\t%7u Secs\n min_time\t\t%7u Secs\n", -+ caps.max_value/10, caps.min_value/10); -+ break; -+ case 4: /* boot time policy does not use these values */ -+ default: -+ break; -+ } -+ printf(" min_corr\t\t%7u secs\n max_corr\t\t%7u secs\n", -+ caps.min_corr/1000, caps.max_corr/1000); -+ printf(" min_stats\t\t%7u secs\n max_stats\t\t%7u secs\n", -+ caps.min_stats, caps.max_stats); -+ printf(" domain scope:\t%s\n", val2str2(caps.scope&0xF, nm_domain_vals)); -+ return 0; -+} -+ -+static int -+ipmi_nm_get_policy(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t option; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ struct nm_get_policy policy; -+ -+ memset(&policy, 0, sizeof(policy)); -+ -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) { -+ print_strs(nm_policy_options, "Get Policy commands", LOG_ERR, 0); -+ return -1; -+ } -+ switch (option) { -+ case 0x03: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ policy.domain |= domain & 0xF; -+ break; -+ case 0x0B: /* policy id */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ lprintf(LOG_ERR," Policy ID must be a positive integer 0-7.\n"); -+ return -1; -+ } -+ break; -+ default: -+ printf(" Unknown command 0x%x, skipping.\n", option); -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if (policy_id == 0xFF) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ if (_ipmi_nm_get_policy(intf, policy.domain, policy_id, &policy)) -+ return -1; -+ if (csv_output) { -+ printf("%s,0x%x,%s,%s,%s,%u,%u,%u,%u,%s\n", -+ val2str2(policy.domain&0xF, nm_domain_vals), -+ policy.domain, -+ (policy.policy_type & 0x10) ? "power" : "nopower ", -+ val2str2(policy.policy_type & 0xF, nm_policy_type_vals), -+ val2str2(policy.policy_exception, nm_exception), -+ policy.policy_limits, -+ policy.corr_time, -+ policy.trigger_limit, -+ policy.stats_period, -+ policy.policy_type & 0x80 ? "volatile" : "non-volatile"); -+ return 0; -+ } -+ printf(" Power domain: %s\n", -+ val2str2(policy.domain&0xF, nm_domain_vals)); -+ printf(" Policy is %s %s%s%s\n", -+ policy.domain&0x10 ? "enabled" : "not enabled", -+ policy.domain&0x20 ? "per Domain " : "", -+ policy.domain&0x40 ? "Globally " : "", -+ policy.domain&0x80 ? "via DCMI api " : ""); -+ printf(" Policy is %sa power control type.\n", (policy.policy_type & 0x10) ? "" : "not "); -+ printf(" Policy Trigger Type: %s\n", -+ val2str2(policy.policy_type & 0xF, nm_policy_type_vals)); -+ printf(" Correction Aggressiveness: %s\n", -+ val2str2((policy.policy_type>> 5) & 0x3, nm_correction_vals)); -+ printf(" Policy Exception Actions: %s\n", -+ val2str2(policy.policy_exception, nm_exception)); -+ printf(" Power Limit: %u Watts\n", -+ policy.policy_limits); -+ printf(" Correction Time Limit: %u milliseconds\n", -+ policy.corr_time); -+ printf(" Trigger Limit: %u units\n", -+ policy.trigger_limit); -+ printf(" Statistics Reporting Period: %u seconds\n", -+ policy.stats_period); -+ printf(" Policy retention: %s\n", -+ policy.policy_type & 0x80 ? "volatile" : "non-volatile"); -+ if ( (policy_id == 0) && ((policy.domain & 0xf) == 0x3) ) -+ printf(" HW Prot Power domain: %s\n", -+ policy.policy_type & 0x80 ? "Secondary" : "Primary"); -+ return 0; -+} -+ -+static int -+ipmi_nm_policy(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t action; -+ uint8_t option; -+ uint8_t correction; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ uint16_t power, period, inlet; -+ uint16_t cores; -+ uint32_t limit; -+ struct nm_policy policy; -+ -+ argv++; -+ argc--; -+ if ((argv[0] == NULL) || -+ ((action = str2val2(argv[0], nm_policy_action)) == 0xFF)) { -+ print_strs(nm_policy_action, "Policy commands", LOG_ERR, 0); -+ return -1; -+ } -+ if (action == 0) /* get */ -+ return (ipmi_nm_get_policy(intf, argc, argv)); -+ memset(&policy, 0, sizeof(policy)); -+ /* -+ * nm policy add [domain ] enable|disable policy_id correction power limit period -+ * nm policy remove [domain ] policy_id -+ * nm policy limiting {domain ] -+ */ -+ while (--argc > 0) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((option = str2val2(argv[0], nm_policy_options)) == 0xFF) { -+ print_strs(nm_policy_options, "Policy options", LOG_ERR, 0); -+ return -1; -+ } -+ switch (option) { -+ case 0x01: /* policy enable */ -+ policy.domain |= IPMI_NM_POLICY_ENABLE; -+ break; -+ case 0x02: /* policy disable */ -+ break; /* value is initialized to zero already */ -+ case 0x03: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ policy.domain |= domain & 0xF; -+ break; -+ case 0x04: /* inlet */ -+ if (str2ushort(argv[1], &inlet) < 0) { -+ printf("Inlet Temp value must be 20-45.\n"); -+ return -1; -+ } -+ policy.policy_type |= 1; -+ policy.policy_limits = 0; -+ policy.trigger_limit = inlet; -+ break; -+ case 0x06: /* get correction action */ -+ if (action == 0x5) break; /* skip if this is a remove */ -+ if ((correction = str2val2(argv[1], nm_correction)) == 0xFF) { -+ print_strs(nm_correction, "Correction Actions", LOG_ERR, 0); -+ return -1; -+ } -+ policy.policy_type |= (correction << 5); -+ break; -+ case 0x07: /* not implemented */ -+ break; -+ case 0x08: /* power */ -+ if (str2ushort(argv[1], &power) < 0) { -+ printf("Power limit value must be 0-500.\n"); -+ return -1; -+ } -+ policy.policy_limits = power; -+ break; -+ case 0x09: /* trigger limit */ -+ if (str2uint(argv[1], &limit) < 0) { -+ printf("Trigger Limit value must be positive integer.\n"); -+ return -1; -+ } -+ policy.corr_time = limit; -+ break; -+ case 0x0A: /* statistics period */ -+ if (str2ushort(argv[1], &period) < 0) { -+ printf("Statistics Reporting Period must be positive integer.\n"); -+ return -1; -+ } -+ policy.stats_period = period; -+ break; -+ case 0x0B: /* policy ID */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ printf("Policy ID must be a positive integer 0-7.\n"); -+ return -1; -+ } -+ policy.policy_id = policy_id; -+ break; -+ case 0x0C: /* volatile */ -+ policy.policy_type |= 0x80; -+ break; -+ case 0x0D: /* cores_off, number of cores to disable at boot time */ -+ policy.policy_type |= 4; -+ if (str2ushort(argv[1], &cores) < 0) { -+ printf("number of cores disabled must be 1-127.\n"); -+ return -1; -+ } -+ if ((cores < 1) || (cores > 127)) { -+ printf("number of cores disabled must be 1-127.\n"); -+ return -1; -+ } -+ policy.policy_type |= 4; -+ policy.policy_limits = cores << 1; -+ break; -+ default: -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if (action == 0x06) { /* limiting */ -+ if ((limit = _ipmi_nm_policy_limiting(intf, domain) == -1)) -+ return -1; -+ printf("limit %x\n", limit); -+ return 0; -+ } -+ if (policy_id == 0xFF) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ if (action == 0x04) /* add */ -+ policy.policy_type |= 0x10; -+ if (_ipmi_nm_set_policy(intf, &policy)) -+ return -1; -+ return 0; -+} -+/* end policy */ -+ -+static int -+ipmi_nm_control(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t action; -+ uint8_t scope = 0; /* default control scope of global */ -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ -+ argv++; -+ argc--; -+ /* nm_ctl_cmds returns 0 for disable, 1 for enable */ -+ if ((argv[0] == NULL) || -+ ((action = str2val2(argv[0], nm_ctl_cmds)) == 0xFF)) { -+ print_strs(nm_ctl_cmds, "Control parameters:", LOG_ERR, 0); -+ print_strs(nm_ctl_domain, "control Scope (required):", LOG_ERR, 0); -+ return -1; -+ } -+ argv++; -+ while (--argc) { -+ /* nm_ctl_domain returns correct bit field except for action */ -+ if ((argv[0] == NULL) || -+ ((scope = str2val2(argv[0], nm_ctl_domain)) == 0xFF)) { -+ print_strs(nm_ctl_domain, "Control Scope (required):", LOG_ERR, 0); -+ return -1; -+ } -+ argv++; -+ if (argv[0] == NULL) break; -+ if (scope == 0x02) { /* domain */ -+ if ((domain = str2val2(argv[0], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ } else if (scope == 0x04) { /* per_policy */ -+ -+ if (str2uchar(argv[0], &policy_id) < 0) { -+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if ((scope == 0x04) && (policy_id == 0xFF)) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ if (_ipmi_nm_control(intf, scope|(action&1), domain, policy_id) < 0 ) -+ return -1; -+ return 0; -+} -+ -+static int -+ipmi_nm_get_statistics(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t mode = 0; -+ uint8_t option; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ int policy_mode = 0; -+ int cut; -+ char *units = ""; -+ char datebuf[27]; -+ struct nm_statistics stats; -+ struct tm tm_t; -+ time_t t; -+ -+ argv++; -+ if ((argv[0] == NULL) || -+ ((mode = str2val2(argv[0], nm_stats_mode)) == 0xFF)) { -+ print_strs(nm_stats_mode, "Statistics commands", LOG_ERR, 0); -+ return -1; -+ } -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) { -+ print_strs(nm_stats_opts, "Control Scope options", LOG_ERR, 0); -+ return -1; -+ } -+ switch (option) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ break; -+ case 0x02: /* policy ID */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ default: -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ -+ switch (mode) { -+ case 0x01: -+ units = "Watts"; -+ break; -+ case 0x02: -+ units = "Celsius"; -+ break; -+ case 0x03: -+ units = "%"; -+ break; -+ case 0x11: -+ case 0x12: -+ case 0x13: -+ policy_mode = 1; -+ units = (mode == 0x11) ? "Watts" : (mode == 0x12) ? "Celsius" : " %"; -+ if (policy_id == 0xFF) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ break; -+ default: -+ break; -+ } -+ if (_ipmi_nm_statistics(intf, mode, domain, policy_id, &stats)) -+ return -1; -+ t = stats.time_stamp; -+ gmtime_r(&t, &tm_t); -+ sprintf(datebuf, "%s", asctime(&tm_t)); -+ cut = strlen(datebuf) -1; -+ datebuf[cut] = 0; -+ if (csv_output) { -+ printf("%s,%s,%s,%s,%s,%d,%d,%d,%d,%s,%d\n", -+ val2str2(stats.id_state & 0xF, nm_domain_vals), -+ ((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" , -+ ((stats.id_state >> 5) & 1) ? "active" : "suspended", -+ ((stats.id_state >> 6) & 1) ? "in progress" : "suspended", -+ ((stats.id_state >> 7) & 1) ? "triggered" : "not triggered", -+ stats.curr_value, -+ stats.min_value, -+ stats.max_value, -+ stats.ave_value, -+ datebuf, -+ stats.stat_period); -+ return 0; -+ } -+ printf(" Power domain: %s\n", -+ val2str2(stats.id_state & 0xF, nm_domain_vals)); -+ printf(" Policy/Global Admin state %s\n", -+ ((stats.id_state >> 4) & 1) ? (policy_mode ? "Policy Enabled" : "Globally Enabled") : "Disabled" ); -+ printf(" Policy/Global Operational state %s\n", -+ ((stats.id_state >> 5) & 1) ? "active" : "suspended"); -+ printf(" Policy/Global Measurement state %s\n", -+ ((stats.id_state >> 6) & 1) ? "in progress" : "suspended"); -+ printf(" Policy Activation state %s\n", -+ ((stats.id_state >> 7) & 1) ? "triggered" : "not triggered"); -+ printf(" Instantaneous reading: %8d %s\n", -+ stats.curr_value, units); -+ printf(" Minimum during sampling period: %8d %s\n", -+ stats.min_value, units); -+ printf(" Maximum during sampling period: %8d %s\n", -+ stats.max_value, units); -+ printf(" Average reading over sample period: %8d %s\n", -+ stats.ave_value, units); -+ printf(" IPMI timestamp: %s\n", -+ datebuf); -+ printf(" Sampling period: %08d Seconds.\n", stats.stat_period); -+ printf("\n"); -+ return 0; -+} -+ -+static int -+ipmi_nm_reset_statistics(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t mode; -+ uint8_t option; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ -+ argv++; -+ if ((argv[0] == NULL) || -+ ((mode = str2val2(argv[0], nm_reset_mode)) == 0xFF)) { -+ print_strs(nm_reset_mode, "Reset Statistics Modes:", LOG_ERR, 0); -+ return -1; -+ } -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((option = str2val2(argv[0], nm_stats_opts)) == 0xFF) { -+ print_strs(nm_stats_opts, "Reset Scope options", LOG_ERR, 0); -+ return -1; -+ } -+ switch (option) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ break; -+ case 0x02: /* policy ID */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ default: -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if (mode && (policy_id == 0xFF)) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ if (_ipmi_nm_reset_stats(intf, mode, domain, policy_id) < 0) -+ return -1; -+ return 0; -+} -+ -+static int -+ipmi_nm_set_range(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t domain = 0; -+ uint8_t param; -+ uint16_t minimum = -1; -+ uint16_t maximum = -1; -+ -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((param = str2val2(argv[0], nm_power_range)) == 0xFF) { -+ print_strs(nm_power_range, "power range parameters:", LOG_ERR, 0); -+ return -1; -+ } -+ switch (param) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ break; -+ case 0x02: /* min */ -+ if (str2ushort(argv[1], &minimum) < 0) { -+ lprintf(LOG_ERR,"Power minimum must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ case 0x03: /* max */ -+ if (str2ushort(argv[1], &maximum) < 0) { -+ lprintf(LOG_ERR,"Power maximum must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ default: -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if ((minimum == 0xFFFF) || (maximum == 0xFFFF)) { -+ lprintf(LOG_ERR,"Missing parameters: nm power range min max .\n"); -+ return -1; -+ } -+ if (_nm_set_range(intf, domain, minimum, maximum) < 0) -+ return -1; -+ return 0; -+} -+ -+static int -+ipmi_nm_get_alert(struct ipmi_intf * intf) -+{ -+ struct nm_set_alert alert; -+ -+ memset(&alert, 0, sizeof(alert)); -+ if (_ipmi_nm_get_alert(intf, &alert)) -+ return -1; -+ if (csv_output) { -+ printf("%d,%s,0x%x,%s,0x%x\n", -+ alert.chan&0xF, -+ (alert.chan >> 7) ? "not registered" : "registered", -+ alert.dest, -+ (alert.string >> 7) ? "yes" : "no", -+ alert.string & 0x7F); -+ return 0; -+ } -+ printf(" Alert Chan: %d\n", -+ alert.chan&0xF); -+ printf(" Alert Receiver: %s\n", -+ (alert.chan >> 7) ? "not registered" : "registered"); -+ printf(" Alert Lan Destination: 0x%x\n", -+ alert.dest); -+ printf(" Use Alert String: %s\n", -+ (alert.string >> 7) ? "yes" : "no"); -+ printf(" Alert String Selector: 0x%x\n", -+ alert.string & 0x7F); -+ return 0; -+} -+ -+static int -+ipmi_nm_alert(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t param; -+ uint8_t action; -+ uint8_t chan = -1; -+ uint8_t dest = -1; -+ uint8_t string = -1; -+ struct nm_set_alert alert; -+ -+ argv++; -+ argc--; -+ if ((argv[0] == NULL) || -+ ((action = str2val2(argv[0], nm_alert_opts)) == 0xFF)) { -+ print_strs(nm_alert_opts, "Alert commands", LOG_ERR, 0); -+ return -1; -+ } -+ if (action == 0x02) /* get */ -+ return (ipmi_nm_get_alert(intf)); -+ /* set */ -+ memset(&alert, 0, sizeof(alert)); -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ if ((param = str2val2(argv[0], nm_set_alert_param)) == 0xFF) { -+ print_strs(nm_set_alert_param, "Set alert Parameters:", LOG_ERR, 0); -+ return -1; -+ } -+ switch (param) { -+ case 0x01: /* channnel */ -+ if (str2uchar(argv[1], &chan) < 0) { -+ lprintf(LOG_ERR,"Alert Lan chan must be a positive integer.\n"); -+ return -1; -+ } -+ if (action == 0x03) /* Clear */ -+ chan |= 0x80; /* deactivate alert reciever */ -+ break; -+ case 0x02: /* dest */ -+ if (str2uchar(argv[1], &dest) < 0) { -+ lprintf(LOG_ERR,"Alert Destination must be a positive integer.\n"); -+ return -1; -+ } -+ break; -+ case 0x03: /* string number */ -+ if (str2uchar(argv[1], &string) < 0) { -+ lprintf(LOG_ERR,"Alert String # must be a positive integer.\n"); -+ return -1; -+ } -+ string |= 0x80; /* set string select flag */ -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ if ((chan == 0xFF) || (dest == 0xFF)) { -+ print_strs(nm_set_alert_param, "Must set alert chan and dest params.", LOG_ERR, 0); -+ return -1; -+ } -+ if (string == 0xFF) string = 0; -+ alert.chan = chan; -+ alert.dest = dest; -+ alert.string = string; -+ if (_ipmi_nm_set_alert(intf, &alert)) -+ return -1; -+ return 0; -+} -+ -+static int -+ipmi_nm_get_thresh(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id) -+{ -+ uint16_t list[3]; -+ -+ memset(list, 0, sizeof(list)); -+ if (_ipmi_nm_get_thresh(intf, domain, policy_id, &list[0])) -+ return -1; -+ -+ printf(" Alert Threshold domain: %s\n", -+ val2str2(domain, nm_domain_vals)); -+ printf(" Alert Threshold Policy ID: %d\n", -+ policy_id); -+ printf(" Alert Threshold 1: %d\n", -+ list[0]); -+ printf(" Alert Threshold 2: %d\n", -+ list[1]); -+ printf(" Alert Threshold 3: %d\n", -+ list[2]); -+ return 0; -+} -+ -+static int -+ipmi_nm_thresh(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t option; -+ uint8_t action; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ struct nm_thresh thresh; -+ int i = 0; -+ -+ argv++; -+ argc--; -+ /* set or get */ -+ if ((argv[0] == NULL) || (argc < 3) || -+ ((action = str2val2(argv[0], nm_thresh_cmds)) == 0xFF)) { -+ print_strs(nm_thresh_cmds, "Theshold commands", LOG_ERR, 0); -+ return -1; -+ } -+ memset(&thresh, 0, sizeof(thresh)); -+ while (--argc) { -+ argv++; -+ if (argv[0] == NULL) break; -+ option = str2val2(argv[0], nm_thresh_param); -+ switch (option) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ argc--; -+ argv++; -+ break; -+ case 0x02: /* policy ID */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n"); -+ return -1; -+ } -+ argc--; -+ argv++; -+ break; -+ case 0xFF: -+ if (i > 2) { -+ lprintf(LOG_ERR,"Set Threshold requires 1, 2, or 3 threshold integer values.\n"); -+ return -1; -+ } -+ if (str2ushort(argv[0], &thresh.thresholds[i++]) < 0) { -+ lprintf(LOG_ERR,"threshold value %d count must be a positve integer.\n", i); -+ return -1; -+ } -+ default: -+ break; -+ } -+ } -+ if (policy_id == 0xFF) { -+ print_strs(nm_stats_opts, "Missing policy_id parameter:", LOG_ERR, 0); -+ return -1; -+ } -+ if (action == 0x02) /* get */ -+ return (ipmi_nm_get_thresh(intf, domain, policy_id)); -+ thresh.domain = domain; -+ thresh.policy_id = policy_id; -+ thresh.count = i; -+ if (_ipmi_nm_set_thresh(intf, &thresh) < 0) -+ return -1; -+ return 0; -+} -+ -+static inline int -+click2hour(int click) -+{ -+ if ((click*6) < 60) return 0; -+ return ((click*6)/60); -+} -+ -+static inline int -+click2min(int click) -+{ -+ if (!click) return 0; -+ if ((click*6) < 60) return click*6; -+ return (click*6)%60; -+} -+ -+static int -+ipmi_nm_get_suspend(struct ipmi_intf *intf, uint8_t domain, uint8_t policy_id) -+{ -+ struct nm_period periods[5]; -+ int i; -+ int j; -+ int count = 0; -+ const char *days[7] = {"M", "Tu", "W", "Th", "F", "Sa", "Su"}; -+ -+ memset(periods, 0, sizeof(periods)); -+ if (_ipmi_nm_get_suspend(intf, domain, policy_id, &count, &periods[0])) -+ return -1; -+ -+ printf(" Suspend Policy domain: %s\n", -+ val2str2(domain, nm_domain_vals)); -+ printf(" Suspend Policy Policy ID: %d\n", -+ policy_id); -+ if (!count) { -+ printf(" No suspend Periods.\n"); -+ return 0; -+ } -+ for (i = 0; i < count; i++) { -+ printf(" Suspend Period %d: %02d:%02d to %02d:%02d", -+ i, click2hour(periods[i].start), click2min(periods[i].start), -+ click2hour(periods[i].stop), click2min(periods[i].stop)); -+ if (periods[i].repeat) printf(", "); -+ for (j = 0; j < 7; j++) -+ printf("%s", (periods[i].repeat >> j)&1 ? days[j] : ""); -+ printf("\n"); -+ } -+ return 0; -+} -+ -+static int -+ipmi_nm_suspend(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ uint8_t option; -+ uint8_t action; -+ uint8_t domain = 0; /* default domain of platform */ -+ uint8_t policy_id = -1; -+ uint8_t count = 0; -+ struct nm_suspend suspend; -+ int i; -+ -+ argv++; -+ argc--; -+ /* set or get */ -+ if ((argv[0] == NULL) || (argc < 3) || -+ ((action = str2val2(argv[0], nm_suspend_cmds)) == 0xFF)) { -+ print_strs(nm_suspend_cmds, "Suspend commands", LOG_ERR, 0); -+ return -1; -+ } -+ memset(&suspend, 0, sizeof(suspend)); -+ while (--argc > 0) { -+ argv++; -+ if (argv[0] == NULL) break; -+ option = str2val2(argv[0], nm_thresh_param); -+ switch (option) { -+ case 0x01: /* get domain scope */ -+ if ((domain = str2val2(argv[1], nm_domain_vals)) == 0xFF) { -+ print_strs(nm_domain_vals, "Domain Scope:", LOG_ERR, 0); -+ return -1; -+ } -+ argc--; -+ argv++; -+ break; -+ case 0x02: /* policy ID */ -+ if (str2uchar(argv[1], &policy_id) < 0) { -+ lprintf(LOG_ERR,"Policy ID must be a positive integer.\n"); -+ return -1; -+ } -+ argc--; -+ argv++; -+ break; -+ case 0xFF: /* process periods */ -+ for (i = 0; count < IPMI_NM_SUSPEND_PERIOD_MAX; i += 3, count++) { -+ if (argc < 3) { -+ lprintf(LOG_ERR,"Error: suspend period requires a start, stop, and repeat values.\n"); -+ return -1; -+ } -+ if (str2uchar(argv[i+0], &suspend.period[count].start) < 0) { -+ lprintf(LOG_ERR,"suspend start value %d must be 0-239.\n", count); -+ return -1; -+ } -+ if (str2uchar(argv[i+1], &suspend.period[count].stop) < 0) { -+ lprintf(LOG_ERR,"suspend stop value %d must be 0-239.\n", count); -+ return -1; -+ } -+ if (str2uchar(argv[i+2], &suspend.period[count].repeat) < 0) { -+ lprintf(LOG_ERR,"suspend repeat value %d unable to convert.\n", count); -+ return -1; -+ } -+ argc -= 3; -+ if (argc <= 0) -+ break; -+ } -+ if (argc <= 0) -+ break; -+ break; -+ default: -+ break; -+ } -+ } -+ if (action == 0x02) /* get */ -+ return (ipmi_nm_get_suspend(intf, domain, policy_id)); -+ -+ suspend.domain = domain; -+ suspend.policy_id = policy_id; -+ if (_ipmi_nm_set_suspend(intf, &suspend) < 0) -+ return -1; -+ return 0; -+} -+/* end nm */ -+ -+static int -+ipmi_dcmi_set_limit(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ int rc = 0; -+ -+ if ( argc == 10) { -+ /* Let`s initialize dcmi power parameters */ -+ struct ipmi_rq req; -+ uint8_t data[256]; -+ uint16_t sample = 0; -+ uint16_t limit = 0; -+ uint32_t correction = 0; -+ struct ipmi_rs *rsp; -+ -+ memset(data, 0, sizeof(data)); -+ memset(&req, 0, sizeof(req)); -+ -+ req.msg.netfn = IPMI_NETFN_DCGRP; -+ req.msg.lun = 0x00; -+ req.msg.cmd = IPMI_DCMI_SETLMT; /* Set power limit */ -+ req.msg.data = data; /* Contents above */ -+ req.msg.data_len = 15; -+ -+ data[0] = IPMI_DCMI; /* Group Extension Identification */ -+ data[1] = 0x0; /* reserved */ -+ data[2] = 0x0; /* reserved */ -+ data[3] = 0x0; /* reserved */ -+ -+ /* action */ -+ switch (str2val2(argv[2], dcmi_pwrmgmt_action_vals)) { -+ case 0x00: -+ /* no_action */ -+ data[4] = 0x00; -+ break; -+ case 0x01: -+ /* power_off */ -+ data[4] = 0x01; -+ break; -+ case 0x11: -+ /* sel_logging*/ -+ data[4] = 0x11; -+ break; -+ case 0xFF: -+ /* error - not a string we knew what to do with */ -+ lprintf(LOG_ERR, "Given Action '%s' is invalid.", -+ argv[2]); -+ return -1; -+ } -+ /* limit */ -+ if (str2ushort(argv[4], &limit) != 0) { -+ lprintf(LOG_ERR, -+ "Given Limit '%s' is invalid.", -+ argv[4]); -+ return (-1); -+ } -+ data[5] = limit >> 0; -+ data[6] = limit >> 8; -+ /* correction */ -+ if (str2uint(argv[6], &correction) != 0) { -+ lprintf(LOG_ERR, -+ "Given Correction '%s' is invalid.", -+ argv[6]); -+ return (-1); -+ } -+ data[7] = correction >> 0; -+ data[8] = correction >> 8; -+ data[9] = correction >> 16; -+ data[10] = correction >> 24; -+ data[11] = 0x00; /* reserved */ -+ data[12] = 0x00; /* reserved */ -+ /* sample */ -+ if (str2ushort(argv[8], &sample) != 0) { -+ lprintf(LOG_ERR, -+ "Given Sample '%s' is invalid.", -+ argv[8]); -+ return (-1); -+ } -+ data[13] = sample >> 0; -+ data[14] = sample >> 8; -+ -+ rsp = intf->sendrecv(intf, &req); -+ if (chk_rsp(rsp)) { -+ return -1; -+ } -+ } else { -+ /* loop through each parameter and value until we have neither */ -+ while ((argv[1] != NULL) && (argv[2] != NULL)) { -+ rc = ipmi_dcmi_pwr_slimit(intf, argv[1], argv[2]); -+ /* catch any error that the set limit function returned */ -+ if (rc > 0) { -+ print_strs(dcmi_pwrmgmt_set_usage_vals, -+ "set_limit ", LOG_ERR, 0); - return -1; - } -- if (str2uchar(argv[2], &entityID) != 0) { -- lprintf(LOG_ERR, -- "Given Entity ID '%s' is invalid.", -- argv[2]); -- return (-1); -- } -- if (str2uchar(argv[3], &entityInst) != 0) { -- lprintf(LOG_ERR, -- "Given Instance ID '%s' is invalid.", -- argv[3]); -- return (-1); -- } -- persistanceFlag = (uint8_t) str2val2(argv[4], dcmi_thermalpolicy_set_parameters_vals); -- actionHardPowerOff = (uint8_t) str2val2(argv[5], dcmi_thermalpolicy_set_parameters_vals); -- actionLogToSEL = (uint8_t) str2val2(argv[6], dcmi_thermalpolicy_set_parameters_vals); -- if (str2uchar(argv[7], &tempLimit) != 0) { -- lprintf(LOG_ERR, -- "Given Temp Limit '%s' is invalid.", -- argv[7]); -- return (-1); -- } -- if (str2ushort(argv[8], &samplingTime) != 0) { -- lprintf(LOG_ERR, -- "Given Sampling Time '%s' is invalid.", -- argv[8]); -- return (-1); -+ /* the first argument is the command and the second is the -+ * value. Move argv two places; what is now 3 will be 1 -+ */ -+ argv+=2; -+ } -+ } -+ return rc; -+} -+ -+static int -+ipmi_dcmi_parse_power(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ int rc = 0; -+ uint8_t sample_time = 0; -+ /* power management */ -+ switch (str2val2(argv[0], dcmi_pwrmgmt_vals)) { -+ case 0x00: -+ /* get reading */ -+ if (argv[1] != NULL) { -+ if (!(sample_time = str2val2(argv[1], dcmi_sampling_vals))) { -+ print_strs(dcmi_sampling_vals, -+ "Invalid sample time. Valid times are: ", -+ LOG_ERR, 1); -+ printf("\n"); -+ return -1; - } -- samplingTimeLSB = (samplingTime & 0xFF); -- samplingTimeMSB = ((samplingTime & 0xFF00) >> 8); -+ } -+ rc = ipmi_dcmi_pwr_rd(intf, sample_time); -+ break; -+ case 0x01: -+ /* get limit */ -+ /* because the get limit function is also used to -+ * populate unchanged values for the set limit -+ * command it returns an ipmi response structure -+ */ -+ rc = ipmi_dcmi_pwr_prnt_glimit(intf); -+ break; -+ case 0x02: -+ /* set limit */ -+ if (argc < 4) { -+ print_strs(dcmi_pwrmgmt_set_usage_vals, -+ "set_limit ", -+ LOG_ERR, 0); -+ return -1; -+ } -+ if (ipmi_dcmi_set_limit(intf, argc, argv) < 0) -+ return -1; -+ rc = ipmi_dcmi_pwr_prnt_glimit(intf); -+ break; -+ case 0x03: -+ /* activate */ -+ rc = ipmi_dcmi_pwr_actdeact(intf, 1); -+ break; -+ case 0x04: -+ /* deactivate */ -+ rc = ipmi_dcmi_pwr_actdeact(intf, 0); -+ break; -+ default: -+ /* no valid options */ -+ print_strs(dcmi_pwrmgmt_vals, -+ "power ", LOG_ERR, 0); -+ break; -+ } -+ return rc; -+} -+/* end dcmi power command */ -+ -+static int -+ipmi_dcmi_thermalpolicy(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ int rc = 0; -+ uint8_t entityID = 0; -+ uint8_t entityInst = 0; -+ uint8_t persistanceFlag; -+ uint8_t actionHardPowerOff; -+ uint8_t actionLogToSEL; -+ uint8_t tempLimit = 0; -+ uint8_t samplingTimeLSB; -+ uint8_t samplingTimeMSB; -+ uint16_t samplingTime = 0; -+ /* Thermal policy get/set */ -+ /* dcmitool dcmi thermalpolicy get */ -+ switch (str2val2(argv[1], dcmi_thermalpolicy_vals)) { -+ case 0x00: -+ if (argc < 4) { -+ lprintf(LOG_NOTICE, "Get "); -+ return -1; -+ } -+ if (str2uchar(argv[2], &entityID) != 0) { -+ lprintf(LOG_ERR, -+ "Given Entity ID '%s' is invalid.", -+ argv[2]); -+ return (-1); -+ } -+ if (str2uchar(argv[3], &entityInst) != 0) { -+ lprintf(LOG_ERR, -+ "Given Instance ID '%s' is invalid.", -+ argv[3]); -+ return (-1); -+ } -+ rc = ipmi_dcmi_getthermalpolicy(intf, entityID, entityInst); -+ break; -+ case 0x01: -+ if (argc < 4) { -+ lprintf(LOG_NOTICE, "Set "); -+ return -1; -+ } else if (argc < 9) { -+ print_strs(dcmi_thermalpolicy_set_parameters_vals, -+ "Set thermalpolicy instance parameters: " -+ " " -+ " " -+ " ", -+ LOG_ERR, 0); -+ return -1; -+ } -+ if (str2uchar(argv[2], &entityID) != 0) { -+ lprintf(LOG_ERR, -+ "Given Entity ID '%s' is invalid.", -+ argv[2]); -+ return (-1); -+ } -+ if (str2uchar(argv[3], &entityInst) != 0) { -+ lprintf(LOG_ERR, -+ "Given Instance ID '%s' is invalid.", -+ argv[3]); -+ return (-1); -+ } -+ persistanceFlag = (uint8_t) str2val2(argv[4], dcmi_thermalpolicy_set_parameters_vals); -+ actionHardPowerOff = (uint8_t) str2val2(argv[5], dcmi_thermalpolicy_set_parameters_vals); -+ actionLogToSEL = (uint8_t) str2val2(argv[6], dcmi_thermalpolicy_set_parameters_vals); -+ if (str2uchar(argv[7], &tempLimit) != 0) { -+ lprintf(LOG_ERR, -+ "Given Temp Limit '%s' is invalid.", -+ argv[7]); -+ return (-1); -+ } -+ if (str2ushort(argv[8], &samplingTime) != 0) { -+ lprintf(LOG_ERR, -+ "Given Sampling Time '%s' is invalid.", -+ argv[8]); -+ return (-1); -+ } -+ samplingTimeLSB = (samplingTime & 0xFF); -+ samplingTimeMSB = ((samplingTime & 0xFF00) >> 8); -+ -+ rc = ipmi_dcmi_setthermalpolicy(intf, -+ entityID, -+ entityInst, -+ persistanceFlag, -+ actionHardPowerOff, -+ actionLogToSEL, -+ tempLimit, -+ samplingTimeLSB, -+ samplingTimeMSB); - -- rc = ipmi_dcmi_setthermalpolicy(intf, -- entityID, -- entityInst, -- persistanceFlag, -- actionHardPowerOff, -- actionLogToSEL, -- tempLimit, -- samplingTimeLSB, -- samplingTimeMSB); -+ break; -+ default: -+ print_strs(dcmi_thermalpolicy_vals, -+ "thermalpolicy ", -+ LOG_ERR, 0); -+ return -1; -+ } -+ return rc; -+} - -- break; -- default: -- print_strs(dcmi_thermalpolicy_vals, -- "thermalpolicy ", -- -1, 0); -+/* main -+ * -+ * @intf: dcmi interface handler -+ * @argc: argument count -+ * @argv: argument vector -+ */ -+int -+ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ int rc = 0; -+ int i; -+ struct ipmi_rs *rsp; -+ -+ if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) { -+ print_strs(dcmi_cmd_vals, -+ "Data Center Management Interface commands", -+ LOG_ERR, 0); -+ return -1; -+ } -+ /* start the cmd requested */ -+ switch (str2val2(argv[0], dcmi_cmd_vals)) { -+ case 0x00: -+ /* discover capabilities*/ -+ for (i = 1; dcmi_capable_vals[i-1].str != NULL; i++) { -+ if (ipmi_dcmi_prnt_getcapabilities(intf, i) < 0) { -+ lprintf(LOG_ERR,"Error discovering %s capabilities!\n", -+ val2str2(i, dcmi_capable_vals)); -+ return -1; -+ } -+ } -+ break; -+ case 0x01: -+ /* power */ -+ argv++; -+ if (argv[0] == NULL) { -+ print_strs(dcmi_pwrmgmt_vals, "power ", -+ LOG_ERR, 0); -+ return -1; -+ } -+ rc = ipmi_dcmi_parse_power(intf, argc, argv); -+ break; -+ /* end power command */ -+ case 0x02: -+ /* sensor print */ -+ /* Look for each item in the dcmi_discvry_snsr_vals struct -+ * and if it exists, print the sdr record id(s) for it. -+ * Use the val from each one as the sensor number. -+ */ -+ for (i = 0; dcmi_discvry_snsr_vals[i].str != NULL; i++) { -+ /* get all of the information about this sensor */ -+ rc = ipmi_dcmi_prnt_discvry_snsr(intf, -+ dcmi_discvry_snsr_vals[i].val); -+ } -+ break; -+ /* end sensor print */ -+ case 0x03: -+ /* asset tag */ -+ if(ipmi_dcmi_prnt_getassettag(intf) < 0) { -+ lprintf(LOG_ERR, "Error getting asset tag!"); -+ return -1; -+ } -+ break; -+ /* end asset tag */ -+ case 0x04: -+ { -+ /* set asset tag */ -+ if (argc == 1 ) { -+ print_strs(dcmi_cmd_vals, -+ "Data Center Management Interface commands", -+ LOG_ERR, 0); -+ return -1; -+ } -+ if (ipmi_dcmi_prnt_setassettag(intf, (uint8_t *)argv[1]) < 0) { -+ lprintf(LOG_ERR, "\nError setting asset tag!"); -+ return -1; -+ } -+ break; -+ } -+ /* end set asset tag */ -+ case 0x05: -+ /* get management controller identifier string */ -+ if (ipmi_dcmi_prnt_getmngctrlids(intf) < 0) { -+ lprintf(LOG_ERR, -+ "Error getting management controller identifier string!"); -+ return -1; -+ } -+ break; -+ /* end get management controller identifier string */ -+ case 0x06: -+ { -+ /* set management controller identifier string */ -+ if (argc == 1 ) { -+ print_strs(dcmi_cmd_vals, -+ "Data Center Management Interface commands", -+ LOG_ERR, 0); -+ return -1; -+ } -+ if (ipmi_dcmi_prnt_setmngctrlids(intf, (uint8_t *)argv[1]) < 0) { -+ lprintf(LOG_ERR, -+ "Error setting management controller identifier string!"); - return -1; - } - break; - } -+ /* end set management controller identifier string */ -+ case 0x07: -+ /* get/set thermal policy */ -+ rc = ipmi_dcmi_thermalpolicy(intf, argc, argv); -+ break; - case 0x08: - if(ipmi_dcmi_prnt_get_temp_readings(intf) < 0 ) { - lprintf(LOG_ERR, - "Error get temperature readings!"); -+ return -1; - } - break; - case 0x09: - if(ipmi_dcmi_prnt_getconfparam(intf) < 0 ) { - lprintf(LOG_ERR, - "Error Get DCMI Configuration Parameters!"); -+ return -1; - }; - break; - case 0x0A: -@@ -2083,7 +3702,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) - if (strncmp(argv[1], "activate_dhcp", 13) != 0) { - print_strs( dcmi_conf_param_vals, - "DCMI Configuration Parameters", -- -1, 0); -+ LOG_ERR, 0); - return -1; - } - break; -@@ -2091,7 +3710,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) - if (argc != 3 || strncmp(argv[1], "help", 4) == 0) { - print_strs(dcmi_conf_param_vals, - "DCMI Configuration Parameters", -- -1, 0); -+ LOG_ERR, 0); - return -1; - } - } -@@ -2132,11 +3751,90 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) - /* couldn't detect what the user entered */ - print_strs(dcmi_cmd_vals, - "Data Center Management Interface commands", -- -1, 0); -+ LOG_ERR, 0); - return -1; - break; - } - printf("\n"); -+ return rc; -+} -+ -+/* Node Manager main -+ * -+ * @intf: nm interface handler -+ * @argc: argument count -+ * @argv: argument vector -+ */ -+int -+ipmi_nm_main(struct ipmi_intf * intf, int argc, char **argv) -+{ -+ struct nm_discover disc; -+ -+ if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) { -+ print_strs(nm_cmd_vals, -+ "Node Manager Interface commands", -+ LOG_ERR, 0); -+ return -1; -+ } -+ -+ switch (str2val2(argv[0], nm_cmd_vals)) { -+ /* discover */ -+ case 0x00: -+ if (_ipmi_nm_discover(intf, &disc)) -+ return -1; -+ printf(" Node Manager Version %s\n", val2str2(disc.nm_version, nm_version_vals)); -+ printf(" revision %d.%d%d patch version %d\n", disc.major_rev, -+ disc.minor_rev>>4, disc.minor_rev&0xf, disc.patch_version); -+ break; -+ /* capability */ -+ case 0x01: -+ if (ipmi_nm_getcapabilities(intf, argc, argv)) -+ return -1; -+ break; -+ /* policy control enable-disable */ -+ case 0x02: -+ if (ipmi_nm_control(intf, argc, argv)) -+ return -1; -+ break; -+ /* policy */ -+ case 0x03: -+ if (ipmi_nm_policy(intf, argc, argv)) -+ return -1; -+ break; -+ /* Get statistics */ -+ case 0x04: -+ if (ipmi_nm_get_statistics(intf, argc, argv)) -+ return -1; -+ break; -+ /* set power draw range */ -+ case 0x05: -+ if (ipmi_nm_set_range(intf, argc, argv)) -+ return -1; -+ break; -+ /* set/get suspend periods */ -+ case 0x06: -+ if (ipmi_nm_suspend(intf, argc, argv)) -+ return -1; -+ break; -+ /* reset statistics */ -+ case 0x07: -+ if (ipmi_nm_reset_statistics(intf, argc, argv)) -+ return -1; -+ break; -+ /* set/get alert destination */ -+ case 0x08: -+ if (ipmi_nm_alert(intf, argc, argv)) -+ return -1; -+ break; -+ /* set/get alert thresholds */ -+ case 0x09: -+ if (ipmi_nm_thresh(intf, argc, argv)) -+ return -1; -+ break; -+ default: -+ print_strs(nm_cmd_vals, "Node Manager Interface commands", LOG_ERR, 0); -+ break; -+ } - return 0; - } - -diff --git a/lib/ipmi_delloem.c b/lib/ipmi_delloem.c -index 308c513..2214c99 100644 ---- a/lib/ipmi_delloem.c -+++ b/lib/ipmi_delloem.c -@@ -273,22 +273,22 @@ ipmi_delloem_main(struct ipmi_intf * intf, int argc, char ** argv) - return 0; - } - if (0 ==strncmp(argv[current_arg], "lcd\0", 4)) { -- ipmi_delloem_lcd_main(intf,argc,argv); -+ rc = ipmi_delloem_lcd_main(intf,argc,argv); - } else if (strncmp(argv[current_arg], "mac\0", 4) == 0) { - /* mac address*/ -- ipmi_delloem_mac_main(intf,argc,argv); -+ rc = ipmi_delloem_mac_main(intf,argc,argv); - } else if (strncmp(argv[current_arg], "lan\0", 4) == 0) { - /* lan address*/ -- ipmi_delloem_lan_main(intf,argc,argv); -+ rc = ipmi_delloem_lan_main(intf,argc,argv); - } else if (strncmp(argv[current_arg], "setled\0", 7) == 0) { - /* SetLED support */ -- ipmi_delloem_setled_main(intf,argc,argv); -+ rc = ipmi_delloem_setled_main(intf,argc,argv); - } else if (strncmp(argv[current_arg], "powermonitor\0", 13) == 0) { - /*Powermanagement report processing*/ -- ipmi_delloem_powermonitor_main(intf,argc,argv); -+ rc = ipmi_delloem_powermonitor_main(intf,argc,argv); - } else if (strncmp(argv[current_arg], "vFlash\0", 7) == 0) { - /* vFlash Support */ -- ipmi_delloem_vFlash_main(intf,argc,argv); -+ rc = ipmi_delloem_vFlash_main(intf,argc,argv); - } else { - usage(); - return -1; -@@ -453,6 +453,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv) - } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - } - } else if ((strncmp(argv[current_arg], "lcdqualifier\0", 13) == 0) -@@ -477,6 +479,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv) - } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - } - } else if ((strncmp(argv[current_arg], "errordisplay\0", 13) == 0) -@@ -499,6 +503,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv) - } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - } - } else if ((strncmp(argv[current_arg], "none\0", 5) == 0) -@@ -529,6 +535,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv) - } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - } - } else if (strncmp(argv[current_arg], "frontpanelaccess\0", 17) == 0) { -@@ -546,16 +554,22 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv) - } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - } - } else if( (strncmp(argv[current_arg], "help\0", 5) == 0) - && (iDRAC_FLAG==0)) { - ipmi_lcd_usage(); - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - return -1; - } - } else { -+ lprintf(LOG_ERR, "Invalid DellOEM command: %s", -+ argv[current_arg]); - ipmi_lcd_usage(); - return -1; - } -@@ -575,7 +589,6 @@ int - ipmi_lcd_get_platform_model_name(struct ipmi_intf * intf, char* lcdstring, - uint8_t max_length, uint8_t field_type) - { -- uint8_t data[4]; - int bytes_copied = 0; - int ii = 0; - int lcdstring_len = 0; -@@ -692,7 +705,6 @@ ipmi_idracvalidator_command(struct ipmi_intf * intf) - static int - ipmi_lcd_get_configure_command_wh(struct ipmi_intf * intf) - { -- uint8_t data[4]; - int rc; - rc = ipmi_mc_getsysinfo(intf, IPMI_DELL_LCD_CONFIG_SELECTOR, 0, 0, - sizeof(lcd_mode), &lcd_mode); -@@ -2047,7 +2059,6 @@ get_nic_selection_mode_12g(struct ipmi_intf* intf,int current_arg, - struct ipmi_rs * rsp; - struct ipmi_rq req; - int failover = 0; -- int nic_selection_mode = 0; - uint8_t input_length = 0; - uint8_t msg_data[30]; - -@@ -2210,7 +2221,6 @@ get_nic_selection_mode_12g(struct ipmi_intf* intf,int current_arg, - static int - get_nic_selection_mode(int current_arg, char ** argv) - { -- int nic_selection_mode = 0; - if (argv[current_arg] != NULL - && strncmp(argv[current_arg], "dedicated\0", 10) == 0) { - return DEDICATED; -@@ -3547,7 +3557,6 @@ ipmi_print_power_consmpt_history(struct ipmi_intf * intf, int unit) - static int - ipmi_get_power_cap(struct ipmi_intf * intf, IPMI_POWER_CAP * ipmipowercap) - { -- uint64_t tempbtuphrconv; - uint8_t *rdata; - int rc; - rc = ipmi_mc_getsysinfo(intf, IPMI_DELL_POWER_CAP, 0, 0, -diff --git a/lib/ipmi_ekanalyzer.c b/lib/ipmi_ekanalyzer.c -index 96d3b44..afee48b 100644 ---- a/lib/ipmi_ekanalyzer.c -+++ b/lib/ipmi_ekanalyzer.c -@@ -399,7 +399,6 @@ ipmi_ekanalyzer_usage(void) - static int - ipmi_ek_get_file_type(char *argument) - { -- int index_name=0; - int filetype = ERROR_STATUS; - if (strlen(argument) <= MIN_ARGUMENT) { - return filetype; -@@ -2773,6 +2772,10 @@ ipmi_ek_display_board_info_area(FILE *input_file, char *board_type, - ret = fread(additional_data, size_board, 1, input_file); - if ((ret != 1) || ferror(input_file)) { - lprintf(LOG_ERR, "Invalid Additional Data!"); -+ if (additional_data != NULL) { -+ free(additional_data); -+ additional_data = NULL; -+ } - goto out; - } - printf("Additional Custom Mfg. Data: %02x", -diff --git a/lib/ipmi_firewall.c b/lib/ipmi_firewall.c -index 8bda398..c3f51ad 100644 ---- a/lib/ipmi_firewall.c -+++ b/lib/ipmi_firewall.c -@@ -512,7 +512,7 @@ _set_command_enables(struct ipmi_intf * intf, - { - struct ipmi_rs * rsp; - struct ipmi_rq req; -- unsigned char * d, rqdata[19]; -+ unsigned char rqdata[19]; - unsigned int c; - - if (!p || !lnfn) { -@@ -568,8 +568,6 @@ _set_command_enables(struct ipmi_intf * intf, - return -1; - } - -- d = rsp->data; -- - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = BMC_SET_COMMAND_ENABLES; -@@ -591,7 +589,6 @@ _set_command_enables(struct ipmi_intf * intf, - return -1; - } - -- d = rsp->data; - return 0; - } - -@@ -1017,7 +1014,8 @@ ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char - { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; - struct bmc_fn_support * bmc_fn_support; -- unsigned int l, n, c, ret; -+ int ret; -+ unsigned int l, n, c; - unsigned char enables[MAX_COMMAND_BYTES]; - - if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { -@@ -1107,10 +1105,15 @@ ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) - { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; - struct bmc_fn_support * bmc_fn_support; -- unsigned int l, n, c, ret; -+ int ret; -+ unsigned int l, n, c; - unsigned char enables[MAX_COMMAND_BYTES]; - -- if (argc > 0 || (argc > 0 && strncmp(argv[0], "help", 4) == 0)) { -+ if (argc < 1) { -+ lprintf(LOG_ERR, "Not enough parameters given."); -+ printf_firewall_usage(); -+ return (-1); -+ } else if (argc > 0 && strncmp(argv[0], "help", 4) == 0) { - printf_firewall_usage(); - return 0; - } -diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c -index 17afe5f..175f044 100644 ---- a/lib/ipmi_fru.c -+++ b/lib/ipmi_fru.c -@@ -958,7 +958,7 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru, - } - } - -- if (fru_area != NULL) { -+ if (fru_data != NULL) { - free(fru_data); - fru_data = NULL; - } -@@ -1082,7 +1082,7 @@ fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru, - break; - } - -- if (fru_area != NULL) { -+ if (fru_data != NULL) { - free(fru_data); - fru_data = NULL; - } -@@ -1217,7 +1217,7 @@ fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru, - break; - } - -- if (fru_area != NULL) { -+ if (fru_data != NULL) { - free(fru_data); - fru_data = NULL; - } -@@ -1564,8 +1564,6 @@ static void ipmi_fru_oemkontron_get( int argc, char ** argv,uint8_t * fru_data, - static int badParams=FALSE; - int start = off; - int offset = start; -- int length = len; -- int i; - offset += sizeof(struct fru_multirec_oem_header); - - if(!badParams){ -@@ -2147,7 +2145,6 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length) - { - unsigned int entries; - unsigned int feeds; -- unsigned int feedcnt; - unsigned int hwaddr; - unsigned int i; - unsigned int id; -@@ -3700,7 +3697,7 @@ ipmi_fru_upg_ekeying(struct ipmi_intf * intf, - char * pFileName, - uint8_t fruId) - { -- struct fru_info fruInfo; -+ struct fru_info fruInfo = {0}; - uint8_t *buf = NULL; - uint32_t offFruMultiRec = 0; - uint32_t fruMultiRecSize = 0; -@@ -4850,8 +4847,6 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId, - struct fru_info fru, struct fru_header header, - uint8_t f_type, uint8_t f_index, char *f_string) - { -- uint8_t msg_data[4]; -- uint8_t checksum; - int i = 0; - uint8_t *fru_data_old = NULL; - uint8_t *fru_data_new = NULL; -diff --git a/lib/ipmi_fwum.c b/lib/ipmi_fwum.c -index 68f40d4..d1e3f4f 100644 ---- a/lib/ipmi_fwum.c -+++ b/lib/ipmi_fwum.c -@@ -571,7 +571,7 @@ KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output, - pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4, - pGetDevId->fw_rev2 & 0x0f); - if (((pBoardInfo->iana == IPMI_OEM_KONTRON) -- && (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002))) { -+ && (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002))) { - printf(" SDR %u", pGetDevId->aux_fw_rev[0]); - } - printf("\n"); -@@ -837,11 +837,8 @@ KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo) - do { - rsp = intf->sendrecv(intf, &req); - } while (rsp == NULL || rsp->ccode == 0xc0); -- if (!rsp) { -- lprintf(LOG_ERR, -- "Error in FWUM Firmware Finish Firmware Image Download Command."); -- return (-1); -- } else if (rsp->ccode != 0) { -+ -+ if (rsp->ccode != 0) { - lprintf(LOG_ERR, - "FWUM Firmware Finish Firmware Image Download returned %x", - rsp->ccode); -@@ -861,7 +858,6 @@ KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer, - unsigned long lastAddress = 0; - unsigned char sequenceNumber = 0; - unsigned char retry = FWUM_MAX_UPLOAD_RETRY; -- unsigned char isLengthValid = 1; - do { - writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize; - /* Reach the end */ -diff --git a/lib/ipmi_hpmfwupg.c b/lib/ipmi_hpmfwupg.c -index fbb5a62..8ada69b 100644 ---- a/lib/ipmi_hpmfwupg.c -+++ b/lib/ipmi_hpmfwupg.c -@@ -998,7 +998,6 @@ HpmfwupgUpgradeStage(struct ipmi_intf *intf, - unsigned char *pImagePtr; - unsigned int actionsSize; - int flagColdReset = FALSE; -- time_t start,end; - /* Put pointer after image header */ - pImagePtr = (unsigned char*) - (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + -@@ -1200,7 +1199,7 @@ HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, - } else { - count = (unsigned short)((pDataTemp+lengthOfBlock) - pData); - } -- memcpy(&uploadCmd.req->data, pData, bufLength); -+ memcpy(&uploadCmd.req->data, pData, count); - imageOffset = 0x00; - blockLength = 0x00; - numTxPkts++; -@@ -1869,7 +1868,6 @@ HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, - struct HpmfwupgUpgradeCtx *pFwupgCtx, - int silent) - { -- int rc = HPMFWUPG_SUCCESS; - struct ipmi_rs *rsp; - struct ipmi_rq req; - pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; -@@ -2196,18 +2194,15 @@ HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req, - lprintf(LOG_DEBUG, "HPM: try to re-open IOL session"); - { - /* force session re-open */ -- intf->opened = 0; -- intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE; -- intf->session->session_id = 0; -- intf->session->in_seq = 0; -- intf->session->out_seq = 0; -- intf->session->active = 0; -- intf->session->retry = 10; -+ intf->abort = 1; -+ intf->close(intf); -+ - while (intf->open(intf) == HPMFWUPG_ERROR - && inaccessTimeoutCounter < inaccessTimeout) { - inaccessTimeoutCounter += (time(NULL) - timeoutSec1); - timeoutSec1 = time(NULL); - } -+ - /* Fake timeout to retry command */ - fakeRsp.ccode = 0xc3; - rsp = &fakeRsp; -diff --git a/lib/ipmi_ime.c b/lib/ipmi_ime.c -index b520ce5..f8e8c09 100755 ---- a/lib/ipmi_ime.c -+++ b/lib/ipmi_ime.c -@@ -431,7 +431,6 @@ static int ImeUpgrade(struct ipmi_intf *intf, char* imageFilename) - if(currentPercent != shownPercent) - { - uint16_t timeElapsedSecond; -- uint16_t timeRemainingSecond; - shownPercent = currentPercent; - printf("Percent: %02i, ", shownPercent); - time(¤t); -@@ -965,8 +964,6 @@ static int ImeManualRollback(struct ipmi_intf *intf) - { - int rc = IME_SUCCESS; - tImeStatus imeStatus; -- time_t start,end,current; -- - - rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_MANUAL_ROLLBACK); - ImeUpdateGetStatus(intf,&imeStatus); -diff --git a/lib/ipmi_isol.c b/lib/ipmi_isol.c -index 0338e36..84d7db8 100644 ---- a/lib/ipmi_isol.c -+++ b/lib/ipmi_isol.c -@@ -413,7 +413,6 @@ ipmi_isol_deactivate(struct ipmi_intf * intf) - struct ipmi_rs * rsp; - struct ipmi_rq req; - uint8_t data[6]; -- struct isol_config_parameters params; - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_ISOL; -diff --git a/lib/ipmi_kontronoem.c b/lib/ipmi_kontronoem.c -index 48dc684..64860be 100644 ---- a/lib/ipmi_kontronoem.c -+++ b/lib/ipmi_kontronoem.c -@@ -105,7 +105,7 @@ ipmi_kontronoem_main(struct ipmi_intf *intf, int argc, char **argv) - if (argc < 2) { - lprintf(LOG_ERR, "Not enough parameters given."); - ipmi_kontron_nextboot_help(); -- rc = (-1); -+ return (-1); - } - rc = ipmi_kontron_nextboot_set(intf, (argc - 1), (argv + 1)); - if (rc == 0) { -@@ -176,7 +176,6 @@ ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf *intf, - struct ipmi_rs *rsp; - struct ipmi_rq req; - uint8_t msg_data[2]; -- int i; - memset(msg_data, 0, sizeof(msg_data)); - /* channel =~ 0x0e => Currently running interface */ - msg_data[0] = channel; -@@ -347,11 +346,28 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf) - /* Position at Board Manufacturer */ - fru_data_offset = (header.offset.board * 8) + 6; - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - /* Position at Board Product Name */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - fru_data_offset_tmp = fru_data_offset; - /* Position at Serial Number */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); -+ if (fru_area == NULL) { -+ lprintf(LOG_ERR, "Failed to read FRU Area string."); -+ free(fru_data); -+ fru_data = NULL; -+ free(sn); -+ sn = NULL; -+ return (-1); -+ } -+ - fru_data_offset++; - if (strlen(fru_area) != sn_size) { - printf("The length of the serial number in the FRU Board Area is wrong.\n"); -@@ -359,7 +375,12 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf) - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - return(-1); -+ } else { -+ free(fru_area); -+ fru_area = NULL; - } - /* Copy the new serial number in the board section saved in memory*/ - memcpy(fru_data + fru_data_offset, sn, sn_size); -@@ -380,6 +401,8 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf) - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - return(-1); - } - /* Set the Product Section */ -@@ -390,26 +413,54 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf) - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - return(-1); - } - /* Position at Product Manufacturer */ - fru_data_offset = (header.offset.product * 8) + 3; - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - /* Position at Product Name */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - /* Position at Product Part */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - /* Position at Product Version */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset); -+ if (fru_area != NULL) { -+ free(fru_area); -+ fru_area = NULL; -+ } - fru_data_offset_tmp = fru_data_offset; - /* Position at Serial Number */ - fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); -+ if (fru_area == NULL) { -+ lprintf(LOG_ERR, "Failed to read FRU Area string."); -+ free(sn); -+ sn = NULL; -+ free(fru_data); -+ fru_data = NULL; -+ return (-1); -+ } - fru_data_offset ++; - if (strlen(fru_area) != sn_size) { - free(sn); - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - printf("The length of the serial number in the FRU Product Area is wrong.\n"); - return(-1); - } -@@ -432,12 +483,16 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf) - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - return -1; - } - free(sn); - sn = NULL; - free(fru_data); - fru_data = NULL; -+ free(fru_area); -+ fru_area = NULL; - return(1); - } - -diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c -index 060e753..bb619eb 100644 ---- a/lib/ipmi_lanp.c -+++ b/lib/ipmi_lanp.c -@@ -53,9 +53,24 @@ - #include - #include - #include -+#include - - extern int verbose; - -+static void print_lan_alert_print_usage(void); -+static void print_lan_alert_set_usage(void); -+static void print_lan_set_usage(void); -+static void print_lan_set_access_usage(void); -+static void print_lan_set_arp_usage(void); -+static void print_lan_set_auth_usage(void); -+static void print_lan_set_bakgw_usage(void); -+static void print_lan_set_cipher_privs_usage(void); -+static void print_lan_set_defgw_usage(void); -+static void print_lan_set_ipsrc_usage(void); -+static void print_lan_set_snmp_usage(void); -+static void print_lan_set_vlan_usage(void); -+static void print_lan_usage(void); -+ - /* is_lan_channel - Check if channel is LAN medium - * - * return 1 if channel is LAN -@@ -530,7 +545,7 @@ lan_set_arp_respond(struct ipmi_intf * intf, - return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1); - } - -- -+/* TODO - probably move elsewhere */ - static char priv_level_to_char(unsigned char priv_level) - { - char ret = 'X'; -@@ -562,7 +577,6 @@ static int - ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) - { - struct lan_param * p; -- int rc = 0; - - if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX) { - lprintf(LOG_ERR, "Invalid Channel %d", chan); -@@ -827,10 +841,29 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) - else - printf("%-24s: Not Available\n", p->desc); - -- return rc; -+ /* Bad Password Threshold */ -+ p = get_lan_param(intf, chan, IPMI_LANP_BAD_PASS_THRESH); -+ if (p == NULL) -+ return -1; -+ if ((p->data != NULL) && (p->data_len == 6)) { -+ int tmp; -+ -+ printf("%-24s: %d\n", p->desc, p->data[1]); -+ printf("%-24s: %s\n", "Invalid password disable", -+ p->data[0] & 1 ? "yes" : "no" ); -+ tmp = p->data[2] + (p->data[3] << 8); -+ printf("%-24s: %d\n", "Attempt Count Reset Int.", tmp * 10); -+ tmp = p->data[4] + (p->data[5] << 8); -+ printf("%-24s: %d\n", "User Lockout Interval", tmp * 10); -+ } else { -+ printf("%-24s: Not Available\n", p->desc); -+ } -+ -+ return 0; - } - - /* Configure Authentication Types */ -+/* TODO - probably some code duplication going on ??? */ - static int - ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * types) - { -@@ -898,272 +931,206 @@ ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * ty - } - - static int --ipmi_lan_set_password(struct ipmi_intf * intf, -- uint8_t userid, uint8_t * password) -+ipmi_lan_set_password(struct ipmi_intf *intf, -+ uint8_t user_id, const char *password) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t data[18]; -- -- memset(&data, 0, sizeof(data)); -- data[0] = userid & 0x3f;/* user ID */ -- data[1] = 0x02; /* set password */ -- -- if (password != NULL) -- memcpy(data+2, password, __min(strlen((const char *)password), 16)); -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x47; -- req.msg.data = data; -- req.msg.data_len = 18; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", userid); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set LAN Password for user %d failed: %s", -- userid, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ int ccode = 0; -+ ccode = _ipmi_set_user_password(intf, user_id, -+ IPMI_PASSWORD_SET_PASSWORD, password, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", -+ user_id); -+ return (-1); - } -- - /* adjust our session password - * or we will no longer be able to communicate with BMC - */ - ipmi_intf_session_set_password(intf, (char *)password); - printf("Password %s for user %d\n", -- (password == NULL) ? "cleared" : "set", userid); -+ (password == NULL) ? "cleared" : "set", user_id); - - return 0; - } - -+/* ipmi_set_alert_enable - enable/disable PEF alerting for given channel. -+ * -+ * @channel - IPMI channel -+ * @enable - whether to enable/disable PEF alerting for given channel -+ * -+ * returns - 0 on success, (-1) on error. -+ */ - static int --ipmi_set_alert_enable(struct ipmi_intf * intf, uint8_t channel, uint8_t enable) -+ipmi_set_alert_enable(struct ipmi_intf *intf, uint8_t channel, uint8_t enable) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t rqdata[3]; -- -- memset(&req, 0, sizeof(req)); -- -- /* update non-volatile access */ -- rqdata[0] = channel; -- rqdata[1] = 0x40; -- -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x41; -- req.msg.data = rqdata; -- req.msg.data_len = 2; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -- -- /* SAVE TO NVRAM */ -- memset(rqdata, 0, 3); -- rqdata[0] = channel & 0xf; -- rqdata[1] = rsp->data[0]; -- if (enable != 0) -- rqdata[1] &= ~0x20; -- else -- rqdata[1] |= 0x20; -- rqdata[1] |= 0x40; -- rqdata[2] = 0; -- -- req.msg.cmd = 0x40; -- req.msg.data_len = 3; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ struct channel_access_t channel_access; -+ int ccode = 0; -+ memset(&channel_access, 0, sizeof(channel_access)); -+ channel_access.channel = channel; -+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Get Channel Access(non-volatile) for channel %d", -+ channel); -+ return (-1); - } -- -- /* SAVE TO CURRENT */ -- rqdata[1] &= 0xc0; -- rqdata[1] |= 0x80; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel); -- return -1; -+ if (enable != 0) { -+ channel_access.alerting = 1; -+ } else { -+ channel_access.alerting = 0; -+ } -+ /* non-volatile */ -+ ccode = _ipmi_set_channel_access(intf, channel_access, 1, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Set Channel Access(non-volatile) for channel %d", -+ channel); -+ return (-1); - } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ /* volatile */ -+ ccode = _ipmi_set_channel_access(intf, channel_access, 2, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Set Channel Access(volatile) for channel %d", -+ channel); -+ return (-1); - } -- -+ printf("PEF alerts for channel %d %s.\n", -+ channel, -+ (enable) ? "enabled" : "disabled"); - return 0; - } - -+/* ipmi_set_channel_access - enable/disable IPMI messaging for given channel and -+ * set Privilege Level to Administrator. -+ * -+ * @channel - IPMI channel -+ * @enable - whether to enable/disable IPMI messaging for given channel. -+ * -+ * returns - 0 on success, (-1) on error -+ */ - static int --ipmi_set_channel_access(struct ipmi_intf * intf, uint8_t channel, uint8_t enable) -+ipmi_set_channel_access(struct ipmi_intf *intf, uint8_t channel, -+ uint8_t enable) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t rqdata[3]; -- uint8_t byteEnable; -- -- memset(&req, 0, sizeof(req)); -- -- /* RETREIVE VALUE IN NVRAM */ -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x41; /* Get Channel Access Command */ -- req.msg.data = rqdata; -- req.msg.data_len = 2; -- -- memset(rqdata, 0, 2); -- rqdata[0] = channel & 0xf; -- rqdata[1] = 0x40; /* retreive NV */ -+ struct channel_access_t channel_access; -+ int ccode = 0; -+ memset(&channel_access, 0, sizeof(channel_access)); -+ channel_access.channel = channel; -+ /* Get Non-Volatile Channel Access first */ -+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Get Channel Access(non-volatile) for channel %d", -+ channel); -+ return (-1); -+ } - -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel); -- return -1; -- } else if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ if (enable != 0) { -+ channel_access.access_mode = 2; - } else { -- byteEnable = *(rsp->data + 0); -+ channel_access.access_mode = 0; -+ } -+ channel_access.privilege_limit = 0x04; -+ ccode = _ipmi_set_channel_access(intf, channel_access, 1, 1); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Set Channel Access(non-volatile) for channel %d", -+ channel); -+ return (-1); - } - -- /* SAVE TO NVRAM */ -- memset(&req, 0, sizeof(req)); -- -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x40; /* Set Channel Access Command */ -- req.msg.data = rqdata; -- req.msg.data_len = 3; -- -- memset(rqdata, 0, 3); -- rqdata[0] = channel & 0xf; -- rqdata[1] = 0x40 | (byteEnable & 0x38); /* use previously set values */ -- if (enable != 0) -- rqdata[1] |= 0x2; /* set always available if enable is set */ -- rqdata[2] = 0x44; /* set channel privilege limit to ADMIN */ -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel); -- return -1; -- } else if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ memset(&channel_access, 0, sizeof(channel_access)); -+ channel_access.channel = channel; -+ /* Get Volatile Channel Access */ -+ ccode = _ipmi_get_channel_access(intf, &channel_access, 1); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Get Channel Access(volatile) for channel %d", -+ channel); -+ return (-1); - } - -- /* RETREIVE VALUE IN NVRAM */ -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x41; /* Get Channel Access Command */ -- req.msg.data = rqdata; -- req.msg.data_len = 2; -- -- memset(rqdata, 0, 2); -- rqdata[0] = channel & 0xf; -- rqdata[1] = 0x80; /* retreive NV */ -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel); -- return -1; -- } else if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ if (enable != 0) { -+ channel_access.access_mode = 2; - } else { -- byteEnable = *(rsp->data + 0); -- } -- -- /* SAVE TO CURRENT */ -- memset(&req, 0, sizeof(req)); -- -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x40; /* Set Channel Access Command */ -- req.msg.data = rqdata; -- req.msg.data_len = 3; -- -- memset(rqdata, 0, 3); -- rqdata[0] = channel & 0xf; -- rqdata[1] = 0x80 | (byteEnable & 0x38); /* use previously set values */ -- if (enable != 0) -- rqdata[1] |= 0x2; /* set always available if enable is set */ -- rqdata[2] = 0x84; /* set channel privilege limit to ADMIN */ -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel); -- return -1; -- } else if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ channel_access.access_mode = 0; -+ } -+ channel_access.privilege_limit = 0x04; -+ ccode = _ipmi_set_channel_access(intf, channel_access, 2, 2); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, -+ "Unable to Set Channel Access(volatile) for channel %d", -+ channel); -+ return (-1); - } - - /* can't send close session if access off so abort instead */ -- if (enable == 0) -+ if (enable == 0) { - intf->abort = 1; -- -+ } -+ printf("Set Channel Access for channel %d was successful.\n", -+ channel); - return 0; - } - -+/* ipmi_set_user_access - set admin access for given user and channel. -+ * -+ * @intf - IPMI interface -+ * @channel - IPMI channel -+ * @user_id - IPMI User ID -+ * -+ * returns - 0 on success, (-1) on error. -+ */ - static int --ipmi_set_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) -+ipmi_set_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t rqdata[4]; -- -- memset(rqdata, 0, 4); -- rqdata[0] = 0x90 | (channel & 0xf); -- rqdata[1] = userid & 0x3f; -- rqdata[2] = 0x4; -- rqdata[3] = 0; -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; -- req.msg.cmd = 0x43; -- req.msg.data = rqdata; -- req.msg.data_len = 4; -- -- rsp = intf->sendrecv(intf, &req); -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Unable to Set User Access for channel %d", channel); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set User Access for channel %d failed: %s", -- channel, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ struct user_access_t user_access; -+ int ccode = 0; -+ memset(&user_access, 0, sizeof(user_access)); -+ user_access.channel = channel; -+ user_access.user_id = user_id; -+ user_access.privilege_limit = 0x04; -+ -+ ccode = _ipmi_set_user_access(intf, &user_access, 1); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Set User Access for channel %d failed", -+ channel); -+ return (-1); -+ } else { -+ printf("Set User Access for channel %d was successful.", -+ channel); -+ return 0; - } -- -- return 0; - } - -+/* 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) -+get_cmdline_macaddr(char *arg, uint8_t *buf) - { -- uint32_t m1, m2, m3, m4, m5, m6; -+ 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; -@@ -1198,8 +1165,7 @@ get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf) - * data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers - * data 9 - maximum priv level for 15th (LSN) cipher. - */ -- bzero(buf, 9); -- -+ memset(buf, 0, 9); - for (i = 0; i < 15; ++i) - { - unsigned char priv_level = IPMI_SESSION_PRIV_ADMIN; -@@ -1256,9 +1222,16 @@ static int - get_cmdline_ipaddr(char * arg, uint8_t * buf) - { - uint32_t ip1, ip2, ip3, ip4; -- if (sscanf(arg, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) { -+ if (sscanf(arg, -+ "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32, -+ &ip1, &ip2, &ip3, &ip4) != 4) { - lprintf(LOG_ERR, "Invalid IP address: %s", arg); -- return -1; -+ return (-1); -+ } -+ if (ip1 > UINT8_MAX || ip2 > UINT8_MAX -+ || ip3 > UINT8_MAX || ip4 > UINT8_MAX) { -+ lprintf(LOG_ERR, "Invalid IP address: %s", arg); -+ return (-1); - } - buf[0] = (uint8_t)ip1; - buf[1] = (uint8_t)ip2; -@@ -1267,55 +1240,8 @@ get_cmdline_ipaddr(char * arg, uint8_t * buf) - return 0; - } - --static void ipmi_lan_set_usage(void) --{ -- lprintf(LOG_NOTICE, "\nusage: lan set \n"); -- lprintf(LOG_NOTICE, "LAN set command/parameter options:"); -- lprintf(LOG_NOTICE, " ipaddr Set channel IP address"); -- lprintf(LOG_NOTICE, " netmask Set channel IP netmask"); -- lprintf(LOG_NOTICE, " macaddr Set channel MAC address"); -- lprintf(LOG_NOTICE, " defgw ipaddr Set default gateway IP address"); -- lprintf(LOG_NOTICE, " defgw macaddr Set default gateway MAC address"); -- lprintf(LOG_NOTICE, " bakgw ipaddr Set backup gateway IP address"); -- lprintf(LOG_NOTICE, " bakgw macaddr Set backup gateway MAC address"); -- lprintf(LOG_NOTICE, " password Set session password for this channel"); -- lprintf(LOG_NOTICE, " snmp Set SNMP public community string"); -- lprintf(LOG_NOTICE, " user Enable default user for this channel"); -- lprintf(LOG_NOTICE, " access Enable or disable access to this channel"); -- lprintf(LOG_NOTICE, " alert Enable or disable PEF alerting for this channel"); -- lprintf(LOG_NOTICE, " arp respond Enable or disable BMC ARP responding"); -- lprintf(LOG_NOTICE, " arp generate Enable or disable BMC gratuitous ARP generation"); -- lprintf(LOG_NOTICE, " arp interval Set gratuitous ARP generation interval"); -- lprintf(LOG_NOTICE, " vlan id > Disable or enable VLAN and set ID (1-4094)"); -- lprintf(LOG_NOTICE, " vlan priority Set vlan priority (0-7)"); -- lprintf(LOG_NOTICE, " auth Set channel authentication types"); -- lprintf(LOG_NOTICE, " level = CALLBACK, USER, OPERATOR, ADMIN"); -- lprintf(LOG_NOTICE, " type = NONE, MD2, MD5, PASSWORD, OEM"); -- lprintf(LOG_NOTICE, " ipsrc Set IP Address source"); -- lprintf(LOG_NOTICE, " none = unspecified source"); -- lprintf(LOG_NOTICE, " static = address manually configured to be static"); -- lprintf(LOG_NOTICE, " dhcp = address obtained by BMC running DHCP"); -- lprintf(LOG_NOTICE, " bios = address loaded by BIOS or system software"); -- lprintf(LOG_NOTICE, " cipher_privs XXXXXXXXXXXXXXX Set RMCP+ cipher suite privilege levels"); -- lprintf(LOG_NOTICE, " X = Cipher Suite Unused"); -- lprintf(LOG_NOTICE, " c = CALLBACK"); -- lprintf(LOG_NOTICE, " u = USER"); -- lprintf(LOG_NOTICE, " o = OPERATOR"); -- lprintf(LOG_NOTICE, " a = ADMIN"); -- lprintf(LOG_NOTICE, " O = OEM\n"); --} -- --static void --ipmi_lan_set_vlan_usage(void) --{ -- lprintf(LOG_NOTICE, -- "lan set vlan id \n" -- "lan set vlan id off\n" -- "lan set vlan priority \n"); --} -- - static int --ipmi_lan_set_vlan_id(struct ipmi_intf * intf, uint8_t chan, char *string) -+ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string) - { - uint8_t data[2]; - int rc; -@@ -1332,8 +1258,8 @@ ipmi_lan_set_vlan_id(struct ipmi_intf * intf, uint8_t chan, char *string) - } - - if (id < 1 || id > 4094) { -- lprintf(LOG_NOTICE, "vlan id must be between 1 and 4094."); -- return -1; -+ lprintf(LOG_NOTICE, "VLAN ID must be between 1 and 4094."); -+ return (-1); - } - else { - data[0] = (uint8_t)id; -@@ -1345,7 +1271,7 @@ ipmi_lan_set_vlan_id(struct ipmi_intf * intf, uint8_t chan, char *string) - } - - static int --ipmi_lan_set_vlan_priority(struct ipmi_intf * intf, uint8_t chan, char *string) -+ipmi_lan_set_vlan_priority(struct ipmi_intf *intf, uint8_t chan, char *string) - { - uint8_t data; - int rc; -@@ -1356,14 +1282,63 @@ ipmi_lan_set_vlan_priority(struct ipmi_intf * intf, uint8_t chan, char *string) - } - - if (priority < 0 || priority > 7) { -- lprintf(LOG_NOTICE, "vlan priority must be between 0 and 7."); -- return -1; -+ lprintf(LOG_NOTICE, "VLAN priority must be between 0 and 7."); -+ return (-1); - } - data = (uint8_t)priority; - rc = set_lan_param(intf, chan, IPMI_LANP_VLAN_PRIORITY, &data, 1); - return rc; - } - -+static void -+print_lan_set_bad_pass_thresh_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set bad_pass_thresh <1|0> \n" -+" Bad Pasword Threshold number.\n" -+" <1|0> 1 = generate a Session Audit sensor event.\n" -+" 0 = do not generate an event.\n" -+" Attempt Count Reset Interval. In tens of seconds.\n" -+" User Lockout Interval. In tens of seconds."); -+} -+ -+/* get_cmdline_bad_pass_thresh - parse-out bad password threshold from given -+ * string and store it into buffer. -+ * -+ * @arg: string to be parsed. -+ * @buf: buffer of 6 to hold parsed Bad Password Threshold. -+ * -+ * returns zero on success, (-1) on error. -+ */ -+static int -+get_cmdline_bad_pass_thresh(char *argv[], uint8_t *buf) -+{ -+ uint16_t reset, lockout; -+ -+ if (str2uchar(argv[0], &buf[1])) { -+ return -1; -+ } -+ -+ if (str2uchar(argv[1], &buf[0]) || buf[0] > 1) { -+ return -1; -+ } -+ -+ if (str2ushort(argv[2], &reset)) { -+ return -1; -+ } -+ -+ if (str2ushort(argv[3], &lockout)) { -+ return -1; -+ } -+ -+ /* store parsed data */ -+ buf[2] = reset & 0xFF; -+ buf[3] = reset >> 8; -+ buf[4] = lockout & 0xFF; -+ buf[5] = lockout >> 8; -+ return 0; -+} -+ - static int - ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - { -@@ -1372,13 +1347,13 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - int rc = 0; - - if (argc < 2) { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return (-1); - } - - if (strncmp(argv[0], "help", 4) == 0 || - strncmp(argv[1], "help", 4) == 0) { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return 0; - } - -@@ -1390,7 +1365,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - /* find type of channel and only accept 802.3 LAN */ - if (!is_lan_channel(intf, chan)) { - lprintf(LOG_ERR, "Channel %d is not a LAN channel!", chan); -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - -@@ -1403,11 +1378,11 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - /* set channel access mode */ - else if (strncmp(argv[1], "access", 6) == 0) { - if (argc < 3) { -- lprintf(LOG_NOTICE, "lan set access "); -+ print_lan_set_access_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, "lan set access "); -+ print_lan_set_access_usage(); - return 0; - } - else if (strncmp(argv[2], "on", 2) == 0) { -@@ -1417,27 +1392,18 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - rc = ipmi_set_channel_access(intf, chan, 0); - } - else { -- lprintf(LOG_NOTICE, "lan set access "); -+ print_lan_set_access_usage(); - return (-1); - } - } - /* set ARP control */ - else if (strncmp(argv[1], "arp", 3) == 0) { - if (argc < 3) { -- lprintf(LOG_NOTICE, -- "lan set arp respond \n" -- "lan set arp generate \n" -- "lan set arp interval \n\n" -- "example: lan set 7 arp gratuitous off\n"); -+ print_lan_set_arp_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, -- "lan set arp respond \n" -- "lan set arp generate \n" -- "lan set arp interval \n\n" -- "example: lan set 7 arp gratuitous off\n"); -- return 0; -+ print_lan_set_arp_usage(); - } - else if (strncmp(argv[2], "interval", 8) == 0) { - uint8_t interval = 0; -@@ -1449,7 +1415,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - } - else if (strncmp(argv[2], "generate", 8) == 0) { - if (argc < 4) { -- lprintf(LOG_NOTICE, "lan set arp generate "); -+ print_lan_set_arp_usage(); - return (-1); - } - else if (strncmp(argv[3], "on", 2) == 0) -@@ -1457,13 +1423,13 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[3], "off", 3) == 0) - rc = lan_set_arp_generate(intf, chan, 0); - else { -- lprintf(LOG_NOTICE, "lan set arp generate "); -+ print_lan_set_arp_usage(); - return (-1); - } - } - else if (strncmp(argv[2], "respond", 7) == 0) { - if (argc < 4) { -- lprintf(LOG_NOTICE, "lan set arp respond "); -+ print_lan_set_arp_usage(); - return (-1); - } - else if (strncmp(argv[3], "on", 2) == 0) -@@ -1471,34 +1437,22 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[3], "off", 3) == 0) - rc = lan_set_arp_respond(intf, chan, 0); - else { -- lprintf(LOG_NOTICE, "lan set arp respond "); -+ print_lan_set_arp_usage(); - return (-1); - } - } - else { -- lprintf(LOG_NOTICE, -- "lan set arp respond \n" -- "lan set arp generate \n" -- "lan set arp interval \n"); -- return (-1); -+ print_lan_set_arp_usage(); - } - } - /* set authentication types */ - else if (strncmp(argv[1], "auth", 4) == 0) { - if (argc < 3) { -- lprintf(LOG_NOTICE, -- "lan set auth \n" -- " level = CALLBACK, USER, OPERATOR, ADMIN\n" -- " types = NONE, MD2, MD5, PASSWORD, OEM\n" -- "example: lan set 7 auth ADMIN PASSWORD,MD5\n"); -+ print_lan_set_auth_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, -- "lan set auth \n" -- " level = CALLBACK, USER, OPERATOR, ADMIN\n" -- " types = NONE, MD2, MD5, PASSWORD, OEM\n" -- "example: lan set 7 auth ADMIN PASSWORD,MD5\n"); -+ print_lan_set_auth_usage(); - return 0; - } else { - rc = ipmi_lan_set_auth(intf, chan, argv[2], argv[3]); -@@ -1507,21 +1461,11 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - /* ip address source */ - else if (strncmp(argv[1], "ipsrc", 5) == 0) { - if (argc < 3) { -- lprintf(LOG_NOTICE, -- "lan set ipsrc \n" -- " none = unspecified\n" -- " static = static address (manually configured)\n" -- " dhcp = address obtained by BMC running DHCP\n" -- " bios = address loaded by BIOS or system software\n"); -+ print_lan_set_ipsrc_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, -- "lan set ipsrc \n" -- " none = unspecified\n" -- " static = static address (manually configured)\n" -- " dhcp = address obtained by BMC running DHCP\n" -- " bios = address loaded by BIOS or system software\n"); -+ print_lan_set_ipsrc_usage(); - return 0; - } - else if (strncmp(argv[2], "none", 4) == 0) -@@ -1533,12 +1477,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[2], "bios", 4) == 0) - data[0] = 3; - else { -- lprintf(LOG_NOTICE, -- "lan set ipsrc \n" -- " none = unspecified\n" -- " static = static address (manually configured)\n" -- " dhcp = address obtained by BMC running DHCP\n" -- " bios = address loaded by BIOS or system software\n"); -+ print_lan_set_ipsrc_usage(); - return -1; - } - rc = set_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC, data, 1); -@@ -1546,16 +1485,16 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - /* session password - * not strictly a lan setting, but its used for lan connections */ - else if (strncmp(argv[1], "password", 8) == 0) { -- rc = ipmi_lan_set_password(intf, 1, (uint8_t *)argv[2]); -+ rc = ipmi_lan_set_password(intf, 1, argv[2]); - } - /* snmp community string */ - else if (strncmp(argv[1], "snmp", 4) == 0) { - if (argc < 3) { -- lprintf(LOG_NOTICE, "lan set snmp "); -+ print_lan_set_snmp_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, "lan set snmp "); -+ print_lan_set_snmp_usage(); - return 0; - } else { - memcpy(data, argv[2], __min(strlen(argv[2]), 18)); -@@ -1568,7 +1507,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[1], "ipaddr", 6) == 0) { - if(argc != 3) - { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - rc = get_cmdline_ipaddr(argv[2], data); -@@ -1583,7 +1522,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[1], "netmask", 7) == 0) { - if(argc != 3) - { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - rc = get_cmdline_ipaddr(argv[2], data); -@@ -1598,7 +1537,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[1], "macaddr", 7) == 0) { - if(argc != 3) - { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - rc = get_cmdline_macaddr(argv[2], data); -@@ -1612,11 +1551,11 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - /* default gateway settings */ - else if (strncmp(argv[1], "defgw", 5) == 0) { - if (argc < 4) { -- lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr"); -+ print_lan_set_defgw_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, "LAN set default gateway Commands: ipaddr, macaddr"); -+ print_lan_set_defgw_usage(); - return 0; - } - else if ((strncmp(argv[2], "ipaddr", 5) == 0) && -@@ -1634,18 +1573,18 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6); - } - else { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - } - /* backup gateway settings */ - else if (strncmp(argv[1], "bakgw", 5) == 0) { - if (argc < 4) { -- lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr"); -+ print_lan_set_bakgw_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- lprintf(LOG_NOTICE, "LAN set backup gateway commands: ipaddr, macaddr"); -+ print_lan_set_bakgw_usage(); - return 0; - } - else if ((strncmp(argv[2], "ipaddr", 5) == 0) && -@@ -1663,17 +1602,17 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6); - } - else { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return -1; - } - } - else if (strncasecmp(argv[1], "vlan", 4) == 0) { - if (argc < 4) { -- ipmi_lan_set_vlan_usage(); -+ print_lan_set_vlan_usage(); - return (-1); - } - else if (strncmp(argv[2], "help", 4) == 0) { -- ipmi_lan_set_vlan_usage(); -+ print_lan_set_vlan_usage(); - return 0; - } - else if (strncasecmp(argv[2], "id", 2) == 0) { -@@ -1688,7 +1627,7 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - ipmi_lan_set_vlan_priority(intf, chan, argv[3]); - } - else { -- ipmi_lan_set_vlan_usage(); -+ print_lan_set_vlan_usage(); - return (-1); - } - } -@@ -1717,25 +1656,13 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - else if (strncmp(argv[1], "cipher_privs", 12) == 0) - { - if (argc != 3) { -- lprintf(LOG_NOTICE, "lan set cipher_privs XXXXXXXXXXXXXXX"); -- lprintf(LOG_NOTICE, " X = Cipher Suite Unused"); -- lprintf(LOG_NOTICE, " c = CALLBACK"); -- lprintf(LOG_NOTICE, " u = USER"); -- lprintf(LOG_NOTICE, " o = OPERATOR"); -- lprintf(LOG_NOTICE, " a = ADMIN"); -- lprintf(LOG_NOTICE, " O = OEM\n"); -+ print_lan_set_cipher_privs_usage(); - return (-1); - } - else if ((strncmp(argv[2], "help", 4) == 0) || - get_cmdline_cipher_suite_priv_data(argv[2], data)) - { -- lprintf(LOG_NOTICE, "lan set cipher_privs XXXXXXXXXXXXXXX"); -- lprintf(LOG_NOTICE, " X = Cipher Suite Unused"); -- lprintf(LOG_NOTICE, " c = CALLBACK"); -- lprintf(LOG_NOTICE, " u = USER"); -- lprintf(LOG_NOTICE, " o = OPERATOR"); -- lprintf(LOG_NOTICE, " a = ADMIN"); -- lprintf(LOG_NOTICE, " O = OEM\n"); -+ print_lan_set_cipher_privs_usage(); - return 0; - } - else -@@ -1743,8 +1670,20 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) - rc = set_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS, data, 9); - } - } -+ else if (strncmp(argv[1], "bad_pass_thresh", 15) == 0) -+ { -+ if (argc == 3 && strncmp(argv[2], "help", 4) == 0) { -+ print_lan_set_bad_pass_thresh_usage(); -+ return 0; -+ } -+ if (argc < 6 || get_cmdline_bad_pass_thresh(&argv[2], data)) { -+ print_lan_set_bad_pass_thresh_usage(); -+ return (-1); -+ } -+ rc = set_lan_param(intf, chan, IPMI_LANP_BAD_PASS_THRESH, data, 6); -+ } - else { -- ipmi_lan_set_usage(); -+ print_lan_set_usage(); - return (-1); - } - -@@ -1865,28 +1804,6 @@ ipmi_lan_alert_print_all(struct ipmi_intf * intf, uint8_t channel) - return 0; - } - --static void --ipmi_lan_alert_print_usage(void) --{ -- lprintf(LOG_NOTICE, "\nusage: lan alert print [channel number] [alert destination]\n"); -- lprintf(LOG_NOTICE, "Default will print all alerts for the first found LAN channel"); --} -- --static void --ipmi_lan_alert_set_usage(void) --{ -- lprintf(LOG_NOTICE, "\nusage: lan alert set \n"); -- lprintf(LOG_NOTICE, " Command/parameter options:\n"); -- lprintf(LOG_NOTICE, " ipaddr Set alert IP address"); -- lprintf(LOG_NOTICE, " macaddr Set alert MAC address"); -- lprintf(LOG_NOTICE, " gateway Set channel gateway to use for alerts"); -- lprintf(LOG_NOTICE, " ack Set Alert Acknowledge on or off"); -- lprintf(LOG_NOTICE, " type Set destination type as PET or OEM"); -- lprintf(LOG_NOTICE, " time Set ack timeout or unack retry interval"); -- lprintf(LOG_NOTICE, " retry Set number of alert retries"); -- lprintf(LOG_NOTICE, ""); --} -- - static int - ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - int argc, char ** argv) -@@ -1896,13 +1813,13 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - int rc = 0; - - if (argc < 2) { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return (-1); - } - - if (strncmp(argv[0], "help", 4) == 0 || - strncmp(argv[1], "help", 4) == 0) { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return 0; - } - -@@ -1960,7 +1877,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - data[2] = 1; - } - else { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return -1; - } - -@@ -1986,7 +1903,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - data[1] &= ~0x80; - } - else { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return -1; - } - rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); -@@ -2014,7 +1931,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - data[1] |= 0x07; - } - else { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return -1; - } - rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); -@@ -2053,7 +1970,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, - rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_TYPE, data, p->data_len); - } - else { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return -1; - } - -@@ -2067,13 +1984,13 @@ ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv) - uint8_t channel = 1; - - if (argc < 1) { -- ipmi_lan_alert_print_usage(); -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_print_usage(); -+ print_lan_alert_set_usage(); - return (-1); - } - else if (strncasecmp(argv[0], "help", 4) == 0) { -- ipmi_lan_alert_print_usage(); -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_print_usage(); -+ print_lan_alert_set_usage(); - return 0; - } - -@@ -2089,7 +2006,7 @@ ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv) - } - - if (strncasecmp(argv[1], "help", 4) == 0) { -- ipmi_lan_alert_print_usage(); -+ print_lan_alert_print_usage(); - return 0; - } - -@@ -2119,11 +2036,11 @@ ipmi_lan_alert(struct ipmi_intf * intf, int argc, char ** argv) - /* alert set [option] */ - if (strncasecmp(argv[0], "set", 3) == 0) { - if (argc < 5) { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return (-1); - } - else if (strncasecmp(argv[1], "help", 4) == 0) { -- ipmi_lan_alert_set_usage(); -+ print_lan_alert_set_usage(); - return 0; - } - -@@ -2268,6 +2185,234 @@ ipmi_lan_stats_clear(struct ipmi_intf * intf, uint8_t chan) - return rc; - } - -+static void -+print_lan_alert_print_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"usage: lan alert print [channel number] [alert destination]"); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"Default will print all alerts for the first found LAN channel"); -+} -+ -+static void -+print_lan_alert_set_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"usage: lan alert set "); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+" Command/parameter options:"); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+" ipaddr Set alert IP address"); -+ lprintf(LOG_NOTICE, -+" macaddr Set alert MAC address"); -+ lprintf(LOG_NOTICE, -+" gateway Set channel gateway to use for alerts"); -+ lprintf(LOG_NOTICE, -+" ack Set Alert Acknowledge on or off"); -+ lprintf(LOG_NOTICE, -+" type Set destination type as PET or OEM"); -+ lprintf(LOG_NOTICE, -+" time Set ack timeout or unack retry interval"); -+ lprintf(LOG_NOTICE, -+" retry Set number of alert retries"); -+ lprintf(LOG_NOTICE, -+""); -+} -+ -+static void -+print_lan_set_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"usage: lan set "); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"LAN set command/parameter options:"); -+ lprintf(LOG_NOTICE, -+" ipaddr Set channel IP address"); -+ lprintf(LOG_NOTICE, -+" netmask Set channel IP netmask"); -+ lprintf(LOG_NOTICE, -+" macaddr Set channel MAC address"); -+ lprintf(LOG_NOTICE, -+" defgw ipaddr Set default gateway IP address"); -+ lprintf(LOG_NOTICE, -+" defgw macaddr Set default gateway MAC address"); -+ lprintf(LOG_NOTICE, -+" bakgw ipaddr Set backup gateway IP address"); -+ lprintf(LOG_NOTICE, -+" bakgw macaddr Set backup gateway MAC address"); -+ lprintf(LOG_NOTICE, -+" password Set session password for this channel"); -+ lprintf(LOG_NOTICE, -+" snmp Set SNMP public community string"); -+ lprintf(LOG_NOTICE, -+" user Enable default user for this channel"); -+ lprintf(LOG_NOTICE, -+" access Enable or disable access to this channel"); -+ lprintf(LOG_NOTICE, -+" alert Enable or disable PEF alerting for this channel"); -+ lprintf(LOG_NOTICE, -+" arp respond Enable or disable BMC ARP responding"); -+ lprintf(LOG_NOTICE, -+" arp generate Enable or disable BMC gratuitous ARP generation"); -+ lprintf(LOG_NOTICE, -+" arp interval Set gratuitous ARP generation interval"); -+ lprintf(LOG_NOTICE, -+" vlan id > Disable or enable VLAN and set ID (1-4094)"); -+ lprintf(LOG_NOTICE, -+" vlan priority Set vlan priority (0-7)"); -+ lprintf(LOG_NOTICE, -+" auth Set channel authentication types"); -+ lprintf(LOG_NOTICE, -+" level = CALLBACK, USER, OPERATOR, ADMIN"); -+ lprintf(LOG_NOTICE, -+" type = NONE, MD2, MD5, PASSWORD, OEM"); -+ lprintf(LOG_NOTICE, -+" ipsrc Set IP Address source"); -+ lprintf(LOG_NOTICE, -+" none = unspecified source"); -+ lprintf(LOG_NOTICE, -+" static = address manually configured to be static"); -+ lprintf(LOG_NOTICE, -+" dhcp = address obtained by BMC running DHCP"); -+ lprintf(LOG_NOTICE, -+" bios = address loaded by BIOS or system software"); -+ lprintf(LOG_NOTICE, -+" cipher_privs XXXXXXXXXXXXXXX Set RMCP+ cipher suite privilege levels"); -+ lprintf(LOG_NOTICE, -+" X = Cipher Suite Unused"); -+ lprintf(LOG_NOTICE, -+" c = CALLBACK"); -+ lprintf(LOG_NOTICE, -+" u = USER"); -+ lprintf(LOG_NOTICE, -+" o = OPERATOR"); -+ lprintf(LOG_NOTICE, -+" a = ADMIN"); -+ lprintf(LOG_NOTICE, -+" O = OEM"); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+" bad_pass_thresh <1|0> \n" -+" Set bad password threshold"); -+} -+ -+static void -+print_lan_set_access_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set access "); -+} -+ -+static void -+print_lan_set_arp_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set arp respond "); -+ lprintf(LOG_NOTICE, -+"lan set arp generate "); -+ lprintf(LOG_NOTICE, -+"lan set arp interval "); -+ lprintf(LOG_NOTICE, -+""); -+ lprintf(LOG_NOTICE, -+"example: lan set 7 arp gratuitous off"); -+} -+ -+static void -+print_lan_set_auth_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set auth "); -+ lprintf(LOG_NOTICE, -+" level = CALLBACK, USER, OPERATOR, ADMIN"); -+ lprintf(LOG_NOTICE, -+" types = NONE, MD2, MD5, PASSWORD, OEM"); -+ lprintf(LOG_NOTICE, -+"example: lan set 7 auth ADMIN PASSWORD,MD5"); -+} -+ -+static void -+print_lan_set_bakgw_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"LAN set backup gateway commands: ipaddr, macaddr"); -+} -+ -+static void -+print_lan_set_cipher_privs_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set cipher_privs XXXXXXXXXXXXXXX"); -+ lprintf(LOG_NOTICE, -+" X = Cipher Suite Unused"); -+ lprintf(LOG_NOTICE, -+" c = CALLBACK"); -+ lprintf(LOG_NOTICE, -+" u = USER"); -+ lprintf(LOG_NOTICE, -+" o = OPERATOR"); -+ lprintf(LOG_NOTICE, -+" a = ADMIN"); -+ lprintf(LOG_NOTICE, -+" O = OEM"); -+ lprintf(LOG_NOTICE, -+""); -+} -+ -+static void -+print_lan_set_defgw_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"LAN set default gateway Commands: ipaddr, macaddr"); -+} -+ -+static void -+print_lan_set_ipsrc_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set ipsrc "); -+ lprintf(LOG_NOTICE, -+" none = unspecified"); -+ lprintf(LOG_NOTICE, -+" static = static address (manually configured)"); -+ lprintf(LOG_NOTICE, -+" dhcp = address obtained by BMC running DHCP"); -+ lprintf(LOG_NOTICE, -+" bios = address loaded by BIOS or system software"); -+} -+ -+static void -+print_lan_set_snmp_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set snmp "); -+} -+ -+static void -+print_lan_set_vlan_usage(void) -+{ -+ lprintf(LOG_NOTICE, -+"lan set vlan id "); -+ lprintf(LOG_NOTICE, -+"lan set vlan id off"); -+ lprintf(LOG_NOTICE, -+"lan set vlan priority "); -+} - - /* - * print_lan_usage -@@ -2275,13 +2420,20 @@ ipmi_lan_stats_clear(struct ipmi_intf * intf, uint8_t chan) - static void - print_lan_usage(void) - { -- lprintf(LOG_NOTICE, "LAN Commands:"); -- lprintf(LOG_NOTICE, " print []"); -- lprintf(LOG_NOTICE, " set "); -- lprintf(LOG_NOTICE, " alert print "); -- lprintf(LOG_NOTICE, " alert set "); -- lprintf(LOG_NOTICE, " stats get []"); -- lprintf(LOG_NOTICE, " stats clear []"); -+ lprintf(LOG_NOTICE, -+"LAN Commands:"); -+ lprintf(LOG_NOTICE, -+" print []"); -+ lprintf(LOG_NOTICE, -+" set "); -+ lprintf(LOG_NOTICE, -+" alert print "); -+ lprintf(LOG_NOTICE, -+" alert set "); -+ lprintf(LOG_NOTICE, -+" stats get []"); -+ lprintf(LOG_NOTICE, -+" stats clear []"); - } - - -@@ -2312,6 +2464,8 @@ ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv) - lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); - return (-1); - } -+ } else { -+ chan = find_lan_channel(intf, 1); - } - if (!is_lan_channel(intf, chan)) { - lprintf(LOG_ERR, "Invalid channel: %d", chan); -@@ -2331,6 +2485,8 @@ ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv) - lprintf(LOG_ERR, "Invalid channel: %s", argv[2]); - return (-1); - } -+ } else { -+ chan = find_lan_channel(intf, 1); - } - if (!is_lan_channel(intf, chan)) { - lprintf(LOG_ERR, "Invalid channel: %d", chan); -diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c -index 2bbbe4b..cfb05f7 100644 ---- a/lib/ipmi_main.c -+++ b/lib/ipmi_main.c -@@ -1,21 +1,21 @@ - /* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. -- * -+ * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: -- * -+ * - * Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. -- * -+ * - * Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. -- * -+ * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. -- * -+ * - * This software is provided "AS IS," without a warranty of any kind. - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A -@@ -29,6 +29,7 @@ - * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, - * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ -+#define _XOPEN_SOURCE 700 - - #include - #include -@@ -263,13 +264,16 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ - * - * This insures that the IOL session gets freed - * for other callers. -- * -+ * - * returns -1 - */ - void ipmi_catch_sigint() - { - if (ipmi_main_intf != NULL) { - printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc); -+ /* reduce retry count to a single retry */ -+ ipmi_main_intf->ssn_params.retry = 1; -+ /* close interface */ - ipmi_main_intf->close(ipmi_main_intf); - } - exit(-1); -@@ -338,6 +342,18 @@ ipmi_parse_hex(const char *str) - return out; - } - -+static uint8_t -+ipmi_acquire_ipmb_address(struct ipmi_intf * intf) -+{ -+ if (intf->picmg_avail) { -+ return ipmi_picmg_ipmb_address(intf); -+ } else if (intf->vita_avail) { -+ return ipmi_vita_ipmb_address(intf); -+ } else { -+ return 0; -+ } -+} -+ - /* ipmi_parse_options - helper function to handle parsing command line options - * - * @argc: count of options -@@ -901,14 +917,22 @@ ipmi_main(int argc, char ** argv, - } - } - /* -- * Attempt picmg discovery of the actual interface address unless -+ * Attempt picmg/vita discovery of the actual interface address unless - * the users specified an address. - * Address specification always overrides discovery - */ -- if (picmg_discover(ipmi_main_intf) && !arg_addr) { -- lprintf(LOG_DEBUG, "Running PICMG Get Address Info"); -- addr = ipmi_picmg_ipmb_address(ipmi_main_intf); -- lprintf(LOG_INFO, "Discovered IPMB-0 address 0x%x", addr); -+ if (picmg_discover(ipmi_main_intf)) { -+ ipmi_main_intf->picmg_avail = 1; -+ } else if (vita_discover(ipmi_main_intf)) { -+ ipmi_main_intf->vita_avail = 1; -+ } -+ -+ if (arg_addr) { -+ addr = arg_addr; -+ } else { -+ lprintf(LOG_DEBUG, "Acquire IPMB address"); -+ addr = ipmi_acquire_ipmb_address(ipmi_main_intf); -+ lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr); - } - - /* -@@ -916,41 +940,44 @@ ipmi_main(int argc, char ** argv, - * used for open, Set the discovered IPMB address as my address if the - * interface supports it. - */ -- if (addr != 0 && addr != ipmi_main_intf->my_addr && -- ipmi_main_intf->set_my_addr) { -- /* -- * Only set the interface address on interfaces which support -- * it -- */ -- (void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); -+ if (addr != 0 && addr != ipmi_main_intf->my_addr) { -+ if (ipmi_main_intf->set_my_addr) { -+ /* -+ * Some interfaces need special handling -+ * when changing local address -+ */ -+ (void)ipmi_main_intf->set_my_addr(ipmi_main_intf, addr); -+ } -+ -+ /* set local address */ -+ ipmi_main_intf->my_addr = addr; - } - -+ ipmi_main_intf->target_addr = ipmi_main_intf->my_addr; -+ - /* If bridging addresses are specified, handle them */ -- if (target_addr > 0) { -- ipmi_main_intf->target_addr = target_addr; -- ipmi_main_intf->target_lun = target_lun ; -- ipmi_main_intf->target_channel = target_channel ; -- } -- if (transit_addr > 0) { -+ if (transit_addr > 0 || target_addr > 0) { - /* sanity check, transit makes no sense without a target */ - if ((transit_addr != 0 || transit_channel != 0) && -- ipmi_main_intf->target_addr == 0) { -+ target_addr == 0) { - lprintf(LOG_ERR, - "Transit address/channel %#x/%#x ignored. " - "Target address must be specified!", - transit_addr, transit_channel); - goto out_free; - } -+ ipmi_main_intf->target_addr = target_addr; -+ ipmi_main_intf->target_channel = target_channel ; - - ipmi_main_intf->transit_addr = transit_addr; - ipmi_main_intf->transit_channel = transit_channel; -- } -- if (ipmi_main_intf->target_addr > 0) { -+ -+ - /* must be admin level to do this over lan */ - ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); - /* Get the ipmb address of the targeted entity */ - ipmi_main_intf->target_ipmb_addr = -- ipmi_picmg_ipmb_address(ipmi_main_intf); -+ ipmi_acquire_ipmb_address(ipmi_main_intf); - lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x", - ipmi_main_intf->target_addr, - ipmi_main_intf->target_channel, -@@ -962,6 +989,9 @@ ipmi_main(int argc, char ** argv, - } - } - -+ /* set target LUN (for RAW command) */ -+ ipmi_main_intf->target_lun = target_lun ; -+ - lprintf(LOG_DEBUG, "Interface address: my_addr %#x " - "transit %#x:%#x target %#x:%#x " - "ipmb_target %#x\n", -diff --git a/lib/ipmi_mc.c b/lib/ipmi_mc.c -index 2890c90..a93134e 100644 ---- a/lib/ipmi_mc.c -+++ b/lib/ipmi_mc.c -@@ -130,43 +130,41 @@ struct bitfield_data { - const char * name; - const char * desc; - uint32_t mask; --}; -- --struct bitfield_data mc_enables_bf[] = { -+} mc_enables_bf[] = { - { -- name: "recv_msg_intr", -- desc: "Receive Message Queue Interrupt", -- mask: 1<<0, -+ .name = "recv_msg_intr", -+ .desc = "Receive Message Queue Interrupt", -+ .mask = 1<<0, - }, - { -- name: "event_msg_intr", -- desc: "Event Message Buffer Full Interrupt", -- mask: 1<<1, -+ .name = "event_msg_intr", -+ .desc = "Event Message Buffer Full Interrupt", -+ .mask = 1<<1, - }, - { -- name: "event_msg", -- desc: "Event Message Buffer", -- mask: 1<<2, -+ .name = "event_msg", -+ .desc = "Event Message Buffer", -+ .mask = 1<<2, - }, - { -- name: "system_event_log", -- desc: "System Event Logging", -- mask: 1<<3, -+ .name = "system_event_log", -+ .desc = "System Event Logging", -+ .mask = 1<<3, - }, - { -- name: "oem0", -- desc: "OEM 0", -- mask: 1<<5, -+ .name = "oem0", -+ .desc = "OEM 0", -+ .mask = 1<<5, - }, - { -- name: "oem1", -- desc: "OEM 1", -- mask: 1<<6, -+ .name = "oem1", -+ .desc = "OEM 1", -+ .mask = 1<<6, - }, - { -- name: "oem2", -- desc: "OEM 2", -- mask: 1<<7, -+ .name = "oem2", -+ .desc = "OEM 2", -+ .mask = 1<<7, - }, - { NULL }, - }; -@@ -217,6 +215,8 @@ printf_sysinfo_usage(int full_help) - lprintf(LOG_NOTICE, " Valid arguments are:"); - } - lprintf(LOG_NOTICE, -+ " system_fw_version System firmware (e.g. BIOS) version"); -+ lprintf(LOG_NOTICE, - " primary_os_name Primary operating system name"); - lprintf(LOG_NOTICE, " os_name Operating system name"); - lprintf(LOG_NOTICE, -@@ -914,6 +914,8 @@ sysinfo_param(const char *str, int *maxset) - else if (!strcmp(str, "delloem_url")) { - *maxset = 2; - return IPMI_SYSINFO_DELL_URL; -+ } else if (!strcmp(str, "system_fw_version")) { -+ return IPMI_SYSINFO_SYSTEM_FW_VERSION; - } - - return (-1); -diff --git a/lib/ipmi_oem.c b/lib/ipmi_oem.c -index 89495c0..96db2ea 100644 ---- a/lib/ipmi_oem.c -+++ b/lib/ipmi_oem.c -@@ -42,34 +42,34 @@ static int ipmi_oem_ibm(struct ipmi_intf * intf); - - static struct ipmi_oem_handle ipmi_oem_list[] = { - { -- name: "supermicro", -- desc: "Supermicro IPMIv1.5 BMC with OEM LAN authentication support", -- setup: ipmi_oem_supermicro, -+ .name = "supermicro", -+ .desc = "Supermicro IPMIv1.5 BMC with OEM LAN authentication support", -+ .setup = ipmi_oem_supermicro, - }, - { -- name: "intelwv2", -- desc: "Intel SE7501WV2 IPMIv1.5 BMC with extra LAN communication support", -+ .name = "intelwv2", -+ .desc = "Intel SE7501WV2 IPMIv1.5 BMC with extra LAN communication support", - }, - { -- name: "intelplus", -- desc: "Intel IPMI 2.0 BMC with RMCP+ communication support", -+ .name = "intelplus", -+ .desc = "Intel IPMI 2.0 BMC with RMCP+ communication support", - }, - { -- name: "icts", -- desc: "IPMI 2.0 ICTS compliance support", -+ .name = "icts", -+ .desc = "IPMI 2.0 ICTS compliance support", - }, - { -- name: "ibm", -- desc: "IBM OEM support", -- setup: ipmi_oem_ibm, -+ .name = "ibm", -+ .desc = "IBM OEM support", -+ .setup = ipmi_oem_ibm, - }, - { -- name: "i82571spt", -- desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode", -+ .name = "i82571spt", -+ .desc = "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode", - }, - { -- name: "kontron", -- desc: "Kontron OEM big buffer support" -+ .name = "kontron", -+ .desc = "Kontron OEM big buffer support" - }, - { 0 } - }; -diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c -index 154bf40..1beebf0 100644 ---- a/lib/ipmi_pef.c -+++ b/lib/ipmi_pef.c -@@ -674,7 +674,7 @@ ipmi_pef_list_policies(struct ipmi_intf * intf) - - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); - if (!tbl_size) { -- if (!ptbl) { -+ if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; - } -@@ -808,7 +808,7 @@ ipmi_pef_get_info(struct ipmi_intf * intf) - uint8_t actions, tbl_size; - - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); -- if (!ptbl) { -+ if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; - } -diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c -index 7a66aa5..9dfa0d1 100644 ---- a/lib/ipmi_picmg.c -+++ b/lib/ipmi_picmg.c -@@ -1745,18 +1745,8 @@ ipmi_picmg_clk_set(struct ipmi_intf * intf, int argc, char ** argv) - } - } - --#if 1 --printf("## ID: %d\n", msg_data[1]); --printf("## index: %d\n", msg_data[2]); --printf("## setting: 0x%02x\n", msg_data[3]); --printf("## family: %d\n", msg_data[4]); --printf("## acc: %d\n", msg_data[5]); --printf("## freq: %ld\n", freq ); --printf("## res: %d\n", msg_data[10]); --#endif - - rsp = intf->sendrecv(intf, &req); -- - if (!rsp) { - lprintf(LOG_ERR, "No valid response received."); - return -1; -@@ -2335,37 +2325,39 @@ picmg_discover(struct ipmi_intf *intf) { - struct ipmi_rq req; - struct ipmi_rs *rsp; - char msg_data; -+ uint8_t picmg_avail = 0; - -- if (intf->picmg_avail == 0) { -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_PICMG; -- req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; -- msg_data = 0x00; -- req.msg.data = &msg_data; -- req.msg.data_len = 1; -- msg_data = 0; -- -- lprintf(LOG_DEBUG, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x", -- intf->my_addr, intf->transit_addr, intf->target_addr); -- rsp = intf->sendrecv(intf, &req); -- if (rsp && !rsp->ccode) { -- if ( (rsp->data[0] == 0) && -- ((rsp->data[1] & 0x0F) == PICMG_ATCA_MAJOR_VERSION -- || (rsp->data[1] & 0x0F) == PICMG_AMC_MAJOR_VERSION) ) { -- intf->picmg_avail = 1; -- lprintf(LOG_DEBUG, "Discovered PICMG Extension %d.%d", -- (rsp->data[1] & 0x0f), (rsp->data[1] >> 4)); -- } -- } else { -- if (rsp == NULL) { -- lprintf(LOG_DEBUG,"No Response from Get PICMG Properties"); -- } else { -- lprintf(LOG_DEBUG,"Error Response %#x from Get PICMG Properities", rsp->ccode); -- } -- } -- } -- if (intf->picmg_avail == 0) { -- lprintf(LOG_DEBUG, "No PICMG Extenstion discovered"); -+ memset(&req, 0, sizeof(req)); -+ req.msg.netfn = IPMI_NETFN_PICMG; -+ req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; -+ msg_data = 0x00; -+ req.msg.data = &msg_data; -+ req.msg.data_len = 1; -+ msg_data = 0; -+ -+ lprintf(LOG_INFO, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x", -+ intf->my_addr, intf->transit_addr, intf->target_addr); -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ lprintf(LOG_INFO,"No response from Get PICMG Properties"); -+ } else if (rsp->ccode != 0) { -+ lprintf(LOG_INFO,"Error response %#x from Get PICMG Properities", -+ rsp->ccode); -+ } else if (rsp->data_len < 4) { -+ lprintf(LOG_INFO,"Invalid Get PICMG Properties response length %d", -+ rsp->data_len); -+ } 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) { -+ lprintf(LOG_INFO,"Unknown PICMG Extension Version %d.%d", -+ (rsp->data[1] & 0x0F), (rsp->data[1] >> 4)); -+ } else { -+ picmg_avail = 1; -+ lprintf(LOG_INFO, "Discovered PICMG Extension Version %d.%d", -+ (rsp->data[1] & 0x0f), (rsp->data[1] >> 4)); - } -- return intf->picmg_avail; -+ -+ return picmg_avail; - } -diff --git a/lib/ipmi_raw.c b/lib/ipmi_raw.c -index 6959c1f..92c0177 100644 ---- a/lib/ipmi_raw.c -+++ b/lib/ipmi_raw.c -@@ -39,13 +39,13 @@ - #include - #include - #include --#include - #include - - #define IPMI_I2C_MASTER_MAX_SIZE 0x40 /* 64 bytes */ - - static int is_valid_param(const char *input_param, uint8_t *uchr_ptr, - const char *label); -+int ipmi_spd_print(uint8_t *, int); - - /* ipmi_master_write_read - Perform I2C write/read transactions - * -@@ -130,7 +130,7 @@ ipmi_master_write_read(struct ipmi_intf * intf, uint8_t bus, uint8_t addr, - return rsp; - } - --#define RAW_SPD_SIZE 256 -+#define RAW_SPD_SIZE 512 - - int - ipmi_rawspd_main(struct ipmi_intf * intf, int argc, char ** argv) -@@ -337,9 +337,6 @@ ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv) - return -1; - } - -- ipmi_intf_session_set_timeout(intf, 15); -- ipmi_intf_session_set_retry(intf, 1); -- - lun = intf->target_lun; - netfn_tmp = str2val(argv[0], ipmi_netfn_vals); - if (netfn_tmp == 0xff) { -diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c -index fa7b082..292a7d3 100644 ---- a/lib/ipmi_sdr.c -+++ b/lib/ipmi_sdr.c -@@ -3977,7 +3977,7 @@ ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile) - } - - while (feof(fp) == 0) { -- memset(&header, 0, 5); -+ memset(&header, 0, sizeof(header)); - bc = fread(&header, 1, 5, fp); - if (bc <= 0) - break; -diff --git a/lib/ipmi_sdradd.c b/lib/ipmi_sdradd.c -index f3bc271..f5bf78a 100644 ---- a/lib/ipmi_sdradd.c -+++ b/lib/ipmi_sdradd.c -@@ -512,7 +512,6 @@ int ipmi_parse_range_list(const char *rangeList, unsigned char * pHexList) - int - ipmi_sdr_add_from_list(struct ipmi_intf *intf, const char *rangeList) - { -- int i; - int rc = 0; - int slave_addr; - int myaddr = intf->target_addr; -@@ -575,7 +574,6 @@ ipmi_sdr_add_from_list(struct ipmi_intf *intf, const char *rangeList) - static int - ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue) - { -- struct sdr_get_rs header; - int rc = 0; - int fd; - uint8_t binHdr[5]; -@@ -633,6 +631,7 @@ ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue) - queue->tail->next = sdrr; - queue->tail = sdrr; - } -+ close(fd); - return rc; - } - -diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c -index 67e12e3..5df66a7 100644 ---- a/lib/ipmi_sel.c -+++ b/lib/ipmi_sel.c -@@ -91,15 +91,22 @@ static int ipmi_sel_oem_readval(char *str) - * reference to byte positions instead of array indexes which (hopefully) - * helps make the code easier to read. - */ --static int ipmi_sel_oem_match(uint8_t *evt, struct ipmi_sel_oem_msg_rec rec) -+static int -+ipmi_sel_oem_match(uint8_t *evt, const struct ipmi_sel_oem_msg_rec *rec) - { -- if (evt[2] == rec.value[SEL_BYTE(3)] && -- ((rec.value[SEL_BYTE(4)] < 0) || (evt[3] == rec.value[SEL_BYTE(4)])) && -- ((rec.value[SEL_BYTE(5)] < 0) || (evt[4] == rec.value[SEL_BYTE(5)])) && -- ((rec.value[SEL_BYTE(6)] < 0) || (evt[5] == rec.value[SEL_BYTE(6)])) && -- ((rec.value[SEL_BYTE(7)] < 0) || (evt[6] == rec.value[SEL_BYTE(7)])) && -- ((rec.value[SEL_BYTE(11)] < 0) || (evt[10] == rec.value[SEL_BYTE(11)])) && -- ((rec.value[SEL_BYTE(12)] < 0) || (evt[11] == rec.value[SEL_BYTE(12)]))) { -+ if (evt[2] == rec->value[SEL_BYTE(3)] -+ && ((rec->value[SEL_BYTE(4)] < 0) -+ || (evt[3] == rec->value[SEL_BYTE(4)])) -+ && ((rec->value[SEL_BYTE(5)] < 0) -+ || (evt[4] == rec->value[SEL_BYTE(5)])) -+ && ((rec->value[SEL_BYTE(6)] < 0) -+ || (evt[5] == rec->value[SEL_BYTE(6)])) -+ && ((rec->value[SEL_BYTE(7)] < 0) -+ || (evt[6] == rec->value[SEL_BYTE(7)])) -+ && ((rec->value[SEL_BYTE(11)] < 0) -+ || (evt[10] == rec->value[SEL_BYTE(11)])) -+ && ((rec->value[SEL_BYTE(12)] < 0) -+ || (evt[11] == rec->value[SEL_BYTE(12)]))) { - return 1; - } else { - return 0; -@@ -191,7 +198,7 @@ static void ipmi_sel_oem_message(struct sel_event_record * evt, int verbose) - int i, j; - - for (i=0; i < sel_oem_nrecs; i++) { -- if (ipmi_sel_oem_match((uint8_t *)evt, sel_oem_msg[i])) { -+ if (ipmi_sel_oem_match((uint8_t *)evt, &sel_oem_msg[i])) { - printf (csv_output ? ",\"%s\"" : " | %s", sel_oem_msg[i].text); - for (j=4; j<17; j++) { - if (sel_oem_msg[i].value[SEL_BYTE(j)] == -3) { -@@ -531,12 +538,10 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) - struct ipmi_rs *rsp; - struct ipmi_rq req; - char *desc = NULL; -- char *str; - int chipset_type = 1; - int data1; - int data2; - int data3; -- int length; - int sensor_type; - uint8_t i = 0; - uint16_t oem_id = 0; -@@ -551,12 +556,12 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) - return NULL; - } - /* Allocate mem for te Description string */ -- desc = (char *)malloc(SIZE_OF_DESC); -+ desc = malloc(sizeof(char) * SIZE_OF_DESC); - if (desc == NULL) { - lprintf(LOG_ERR, "ipmitool: malloc failure"); - return NULL; - } -- memset(desc,0,SIZE_OF_DESC); -+ memset(desc, '\0', SIZE_OF_DESC); - sensor_type = rec->sel_type.standard_type.sensor_type; - switch (sensor_type) { - case SENSOR_TYPE_MEMORY: -@@ -587,17 +592,19 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) - /* check the chipset type */ - oem_id = ipmi_get_oem_id(intf); - if (oem_id == 0) { -+ if (desc != NULL) { -+ free(desc); -+ desc = NULL; -+ } - return NULL; - } -- length = sizeof(supermicro_X8); -- for (i = 0; i < length; i++) { -+ for (i = 0; supermicro_X8[i] != 0xFFFF; i++) { - if (oem_id == supermicro_X8[i]) { - chipset_type = 0; - break; - } - } -- length = sizeof(supermicro_x9); -- for (i = 0; i < length; i++) { -+ for (i = 0; supermicro_x9[i] != 0xFFFF; i++) { - if (oem_id == supermicro_x9[i]) { - chipset_type = 2; - break; -@@ -616,7 +623,8 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) - (data2 >> 4) + 0x40 + (data3 & 0x3) * 3, - (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); - } else { -- snprintf(desc, SIZE_OF_DESC, ""); -+ /* No description. */ -+ desc[0] = '\0'; - } - break; - case SENSOR_TYPE_SUPERMICRO_OEM: -@@ -650,17 +658,13 @@ char * get_dell_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) - - unsigned char count; - unsigned char node; -- unsigned char num; - unsigned char dimmNum; - unsigned char dimmsPerNode; - char dimmStr[MAX_DIMM_STR]; -- char cardStr[MAX_CARD_STR]; -- char numStr[MAX_CARDNO_STR]; - char tmpdesc[SIZE_OF_DESC]; - char* str; - unsigned char incr = 0; - unsigned char i=0,j = 0; -- unsigned char postCode; - struct ipmi_rs *rsp; - struct ipmi_rq req; - char tmpData; -@@ -1234,6 +1238,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char - sfx = ipmi_get_oem_desc(intf, rec); - break; - /* add your oem sensor assignation here */ -+ default: -+ break; - } - if( evt == NULL ){ - lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", -@@ -1247,6 +1253,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char - code = rec->sel_type.standard_type.sensor_type; - sfx = ipmi_get_oem_desc(intf, rec); - break; -+ default: -+ break; - } - } - if( evt == NULL ){ -@@ -1915,6 +1923,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) - case IPMI_OEM_SUPERMICRO_47488: - print_sensor = 0; - break; -+ default: -+ break; - } - /* - * Sensor-Specific Discrete -@@ -2832,7 +2842,6 @@ ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv) - - for (; argc != 0; argc--) - { -- id = (uint16_t) strtoul(argv[argc-1], NULL, 0); - if (str2ushort(argv[argc-1], &id) != 0) { - lprintf(LOG_ERR, "Given SEL ID '%s' is invalid.", - argv[argc-1]); -@@ -2869,25 +2878,27 @@ ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv) - static int - ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv) - { -- uint16_t id; -- int i, oldv; -- struct sel_event_record evt; -- struct sdr_record_list * sdr; - struct entity_id entity; -- struct sdr_record_list * list, * entry; -+ struct sdr_record_list *entry; -+ struct sdr_record_list *list; -+ struct sdr_record_list *sdr; -+ struct sel_event_record evt; -+ int i; -+ int oldv; - int rc = 0; -+ uint16_t id; - - if (argc == 0 || strncmp(argv[0], "help", 4) == 0) { - lprintf(LOG_ERR, "usage: sel get ..."); -- return -1; -+ return (-1); - } - - if (ipmi_sel_reserve(intf) == 0) { - lprintf(LOG_ERR, "Unable to reserve SEL"); -- return -1; -+ return (-1); - } - -- for (i=0; itype) { - case SDR_RECORD_TYPE_FULL_SENSOR: - case SDR_RECORD_TYPE_COMPACT_SENSOR: -@@ -2947,8 +2963,9 @@ ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv) - ipmi_fru_print(intf, entry->record.fruloc); - } - -- if ((argc > 1) && (i<(argc-1))) -+ if ((argc > 1) && (i < (argc - 1))) { - printf("----------------------\n\n"); -+ } - } - - return rc; -diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c -index c138c67..063dfb0 100644 ---- a/lib/ipmi_sensor.c -+++ b/lib/ipmi_sensor.c -@@ -1,21 +1,21 @@ - /* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. -- * -+ * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: -- * -+ * - * Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. -- * -+ * - * Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. -- * -+ * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. -- * -+ * - * This software is provided "AS IS," without a warranty of any kind. - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A -@@ -52,8 +52,8 @@ void print_sensor_thresh_usage(); - // static - int - ipmi_sensor_get_sensor_reading_factors( -- struct ipmi_intf * intf, -- struct sdr_record_full_sensor * sensor, -+ struct ipmi_intf * intf, -+ struct sdr_record_full_sensor * sensor, - uint8_t reading) - { - struct ipmi_rq req; -@@ -88,9 +88,9 @@ ipmi_sensor_get_sensor_reading_factors( - return -1; - } else { - /* Update SDR copy with updated Reading Factors for this reading */ -- /* Note: -- * The Format of the returned data is exactly as in the SDR definition (Little Endian Format), -- * therefore we can use raw copy operation here. -+ /* Note: -+ * The Format of the returned data is exactly as in the SDR definition (Little Endian Format), -+ * therefore we can use raw copy operation here. - * Note: rsp->data[0] would point to the next valid entry in the sampling table - */ - // BUGBUG: uses 'hardcoded' length information from SDR Definition -@@ -160,7 +160,6 @@ ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf, - struct sdr_record_common_sensor *sensor, - uint8_t sdr_record_type) - { -- const char *id; - struct sensor_reading *sr; - - sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3); -@@ -892,8 +891,20 @@ ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv) - /* need to set verbose level to 1 */ - v = verbose; - verbose = 1; -- if (ipmi_sdr_print_listentry(intf, sdr) < 0) { -- rc = (-1); -+ switch (sdr->type) { -+ case SDR_RECORD_TYPE_FULL_SENSOR: -+ case SDR_RECORD_TYPE_COMPACT_SENSOR: -+ if (ipmi_sensor_print_fc(intf, -+ (struct sdr_record_common_sensor *) sdr->record.common, -+ sdr->type)) { -+ rc = -1; -+ } -+ break; -+ default: -+ if (ipmi_sdr_print_listentry(intf, sdr) < 0) { -+ rc = (-1); -+ } -+ break; - } - verbose = v; - sdr = NULL; -diff --git a/lib/ipmi_sol.c b/lib/ipmi_sol.c -index cf58b44..5415ea7 100644 ---- a/lib/ipmi_sol.c -+++ b/lib/ipmi_sol.c -@@ -544,8 +544,8 @@ ipmi_get_sol_info( - case 0x80: - if( intf->session != NULL ) { - lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d", -- val2str(data[1], sol_parameter_vals), intf->session->port); -- params->payload_port = intf->session->port; -+ val2str(data[1], sol_parameter_vals), intf->ssn_params.port); -+ params->payload_port = intf->ssn_params.port; - } else { - lprintf(LOG_ERR, - "Info: SOL parameter '%s' not supported - can't determine which " -@@ -1235,14 +1235,14 @@ printSolEscapeSequences(struct ipmi_intf * intf) - %c? - this message\n\ - %c%c - send the escape character by typing it twice\n\ - (Note that escapes are only recognized immediately after newline.)\n", -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char); - } - - -@@ -1300,7 +1300,7 @@ ipmi_sol_deactivate(struct ipmi_intf * intf, int instance) - req.msg.data_len = 6; - req.msg.data = data; - -- bzero(data, sizeof(data)); -+ memset(data, 0, sizeof(data)); - data[0] = IPMI_PAYLOAD_TYPE_SOL; /* payload type */ - data[1] = instance; /* payload instance. */ - -@@ -1379,25 +1379,25 @@ processSolUserInput( - switch (ch) { - case '.': - printf("%c. [terminated ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - retval = 1; - break; - - case 'Z' - 64: - printf("%c^Z [suspend ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - suspendSelf(1); /* Restore tty back to raw */ - continue; - - case 'X' - 64: - printf("%c^Z [suspend ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - suspendSelf(0); /* Don't restore to raw mode */ - continue; - - case 'B': - printf("%cB [send break]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - sendBreak(intf); - continue; - -@@ -1406,16 +1406,16 @@ processSolUserInput( - continue; - - default: -- if (ch != intf->session->sol_escape_char) -+ if (ch != intf->ssn_params.sol_escape_char) - v2_payload.payload.sol_packet.data[length++] = -- intf->session->sol_escape_char; -+ intf->ssn_params.sol_escape_char; - v2_payload.payload.sol_packet.data[length++] = ch; - } - } - - else - { -- if (last_was_cr && (ch == intf->session->sol_escape_char)) { -+ if (last_was_cr && (ch == intf->ssn_params.sol_escape_char)) { - escape_pending = 1; - continue; - } -@@ -1441,7 +1441,7 @@ processSolUserInput( - struct ipmi_rs * rsp = NULL; - int try = 0; - -- while (try < intf->session->retry) { -+ while (try < intf->ssn_params.retry) { - - v2_payload.payload.sol_packet.character_count = length; - -@@ -1827,12 +1827,12 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval, - - /* NOTE: the spec does allow for SOL traffic to be sent on - * a different port. we do not yet support that feature. */ -- if (intf->session->sol_data.port != intf->session->port) -+ if (intf->session->sol_data.port != intf->ssn_params.port) - { - /* try byteswapping port in case BMC sent it incorrectly */ - uint16_t portswap = BSWAP_16(intf->session->sol_data.port); - -- if (portswap == intf->session->port) { -+ if (portswap == intf->ssn_params.port) { - intf->session->sol_data.port = portswap; - } - else { -@@ -1842,7 +1842,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval, - } - - printf("[SOL Session operational. Use %c? for help]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - - if(looptest == 1) - { -@@ -1942,10 +1942,6 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv) - print_sol_usage(); - return -1; - } -- if (argc == 1 || argc > 4) { -- print_sol_usage(); -- return -1; -- } - if (argc >= 3) { - if (is_ipmi_channel_num(argv[2], &channel) != 0) { - return (-1); -diff --git a/lib/ipmi_strings.c b/lib/ipmi_strings.c -index 277b82f..4a1ff46 100644 ---- a/lib/ipmi_strings.c -+++ b/lib/ipmi_strings.c -@@ -68,6 +68,9 @@ const struct valstr ipmi_oem_info[] = { - { 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_ADVANTECH, "Advantech" }, - { 0xffff , NULL }, - }; - -@@ -115,6 +118,90 @@ const struct oemvalstr ipmi_oem_product_info[] = { - { IPMI_OEM_KONTRON,5303, "AT8901" }, - /* Broadcom */ - { IPMI_OEM_BROADCOM, 5725, "BCM5725" }, -+ /* Ericsson */ -+ { IPMI_OEM_ERICSSON, 0x0054, "Phantom" }, -+ /* Advantech */ -+ /* ATCA Blades */ -+ { IPMI_OEM_ADVANTECH, 0x3393, "MIC-3393" }, -+ { IPMI_OEM_ADVANTECH, 0x3395, "MIC-3395" }, -+ { IPMI_OEM_ADVANTECH, 0x3396, "MIC-3396" }, -+ { IPMI_OEM_ADVANTECH, 0x5302, "MIC-5302" }, -+ { IPMI_OEM_ADVANTECH, 0x5304, "MIC-5304" }, -+ { IPMI_OEM_ADVANTECH, 0x5320, "MIC-5320" }, -+ { IPMI_OEM_ADVANTECH, 0x5321, "MIC-5321" }, -+ { IPMI_OEM_ADVANTECH, 0x5322, "MIC-5322" }, -+ { IPMI_OEM_ADVANTECH, 0x5332, "MIC-5332" }, -+ { IPMI_OEM_ADVANTECH, 0x5333, "MIC-5333" }, -+ { IPMI_OEM_ADVANTECH, 0x5342, "MIC-5342" }, -+ { IPMI_OEM_ADVANTECH, 0x5343, "MIC-5343" }, -+ { IPMI_OEM_ADVANTECH, 0x5344, "MIC-5344" }, -+ { IPMI_OEM_ADVANTECH, 0x5345, "MIC-5345" }, -+ { IPMI_OEM_ADVANTECH, 0x5201, "MIC-5201 Dual 10GE AMC"}, -+ { IPMI_OEM_ADVANTECH, 0x5203, "MIC-5203 Quad GbE AMC"}, -+ { IPMI_OEM_ADVANTECH, 0x5212, "MIC-5212 Dual 10GE AMC"}, -+ /* AdvancedMC */ -+ { IPMI_OEM_ADVANTECH, 0x5401, "MIC-5401" }, -+ { IPMI_OEM_ADVANTECH, 0x5601, "MIC-5601" }, -+ { IPMI_OEM_ADVANTECH, 0x5602, "MIC-5602" }, -+ { IPMI_OEM_ADVANTECH, 0x5604, "MIC-5604" }, -+ { IPMI_OEM_ADVANTECH, 0x5603, "MIC-5603" }, -+ { IPMI_OEM_ADVANTECH, 0x6311, "MIC-6311" }, -+ { IPMI_OEM_ADVANTECH, 0x6313, "MIC-6313" }, -+ { IPMI_OEM_ADVANTECH, 0x8301, "MIC-8301" }, -+ { IPMI_OEM_ADVANTECH, 0x8302, "MIC-8302" }, -+ { IPMI_OEM_ADVANTECH, 0x8304, "MIC-8304" }, -+ { IPMI_OEM_ADVANTECH, 0x5101, "RTM-5101" }, -+ { IPMI_OEM_ADVANTECH, 0x5102, "RTM-5102" }, -+ { IPMI_OEM_ADVANTECH, 0x5106, "RTM-5106" }, -+ { IPMI_OEM_ADVANTECH, 0x5107, "RTM-5107" }, -+ { IPMI_OEM_ADVANTECH, 0x5210, "RTM-5210" }, -+ { IPMI_OEM_ADVANTECH, 0x5220, "RTM-5220" }, -+ { IPMI_OEM_ADVANTECH, 0x5104, "RTM-5104" }, -+ { IPMI_OEM_ADVANTECH, 0x5500, "UTCA-5500"}, -+ { IPMI_OEM_ADVANTECH, 0x5503, "UTCA-5503"}, -+ { IPMI_OEM_ADVANTECH, 0x5504, "UTCA-5504"}, -+ { IPMI_OEM_ADVANTECH, 0x5801, "UTCA-5801"}, -+ { IPMI_OEM_ADVANTECH, 0x2210, "NCPB-2210"}, -+ { IPMI_OEM_ADVANTECH, 0x2305, "NCPB-2305"}, -+ { IPMI_OEM_ADVANTECH, 0x2320, "NCPB-2320"}, -+ { IPMI_OEM_ADVANTECH, 0x3109, "NCP-3109" }, -+ { IPMI_OEM_ADVANTECH, 0x3110, "NCP-3110" }, -+ { IPMI_OEM_ADVANTECH, 0x3200, "NCP-3200" }, -+ { IPMI_OEM_ADVANTECH, 0x5060, "SMM-5060" }, -+ { IPMI_OEM_ADVANTECH, 0x3210, "FWA-3210" }, -+ { IPMI_OEM_ADVANTECH, 0x3220, "FWA-3220" }, -+ { IPMI_OEM_ADVANTECH, 0x3221, "FWA-3221" }, -+ { IPMI_OEM_ADVANTECH, 0x3230, "FWA-3230" }, -+ { IPMI_OEM_ADVANTECH, 0x3231, "FWA-3231" }, -+ { IPMI_OEM_ADVANTECH, 0x3233, "FWA-3233" }, -+ { IPMI_OEM_ADVANTECH, 0x3250, "FWA-3250" }, -+ { IPMI_OEM_ADVANTECH, 0x3260, "FWA-3260" }, -+ { IPMI_OEM_ADVANTECH, 0x5020, "FWA-5020" }, -+ { IPMI_OEM_ADVANTECH, 0x6510, "FWA-6510" }, -+ { IPMI_OEM_ADVANTECH, 0x6511, "FWA-6511" }, -+ { IPMI_OEM_ADVANTECH, 0x6512, "FWA-6512" }, -+ { IPMI_OEM_ADVANTECH, 0x6520, "FWA-6520" }, -+ { IPMI_OEM_ADVANTECH, 0x6521, "FWA-6521" }, -+ { IPMI_OEM_ADVANTECH, 0x6522, "FWA-6522" }, -+ { IPMI_OEM_ADVANTECH, 0x7310, "ATCA-7310"}, -+ { IPMI_OEM_ADVANTECH, 0x7330, "ATCA-7330"}, -+ { IPMI_OEM_ADVANTECH, 0x7410, "ATCA-7410"}, -+ { IPMI_OEM_ADVANTECH, 0x9023, "ATCA-9023"}, -+ { IPMI_OEM_ADVANTECH, 0x9112, "ATCA-9112"}, -+ { IPMI_OEM_ADVANTECH, 0x4201, "AMC-4201" }, -+ { IPMI_OEM_ADVANTECH, 0x4202, "AMC-4202" }, -+ { IPMI_OEM_ADVANTECH, 0x3211, "NAMB-3211"}, -+ { IPMI_OEM_ADVANTECH, 0x1207, "CPCI-1207"}, -+ { IPMI_OEM_ADVANTECH, 0x120E, "CPCI-1207 Test Board"}, -+ { IPMI_OEM_ADVANTECH, 0x1304, "CPCI-1304"}, -+ { IPMI_OEM_ADVANTECH, 0x7001, "CPCI-7001"}, -+ { IPMI_OEM_ADVANTECH, 0x8220, "CPCI-8220"}, -+ { IPMI_OEM_ADVANTECH, 0x9001, "ESP-9001" }, -+ { IPMI_OEM_ADVANTECH, 0x9002, "ESP-9002" }, -+ { IPMI_OEM_ADVANTECH, 0x9012, "ESP-9012" }, -+ { IPMI_OEM_ADVANTECH, 0x9212, "ESP-9212" }, -+ { IPMI_OEM_ADVANTECH, 0x6000, "CGS-6000" }, -+ { IPMI_OEM_ADVANTECH, 0x6010, "CGS-6010" }, - - { 0xffffff , 0xffff , NULL }, - }; -diff --git a/lib/ipmi_sunoem.c b/lib/ipmi_sunoem.c -index 16a6090..7f7a58b 100644 ---- a/lib/ipmi_sunoem.c -+++ b/lib/ipmi_sunoem.c -@@ -1361,9 +1361,6 @@ ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[]) - - /* Fill in data packet */ - for (i = 0; i < ECHO_DATA_SIZE; i++) { -- if (i > UINT8_MAX) -- break; -- - echo_req.data[i] = (uint8_t) i; - } - -diff --git a/lib/ipmi_tsol.c b/lib/ipmi_tsol.c -index b4e3cc1..70d7357 100644 ---- a/lib/ipmi_tsol.c -+++ b/lib/ipmi_tsol.c -@@ -29,6 +29,7 @@ - * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, - * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ -+#define _DEFAULT_SOURCE - - #include - #include -@@ -184,12 +185,12 @@ print_escape_seq(struct ipmi_intf *intf) - " %c? - this message\n" - " %c%c - send the escape character by typing it twice\n" - " (Note that escapes are only recognized immediately after newline.)", -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char, -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char, -+ intf->ssn_params.sol_escape_char); - } - - static int -@@ -263,7 +264,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len) - for(i = 0; i < len ;) { - if (!in_esc) { - if (last_was_cr && -- (in_buff[i] == intf->session->sol_escape_char)) { -+ (in_buff[i] == intf->ssn_params.sol_escape_char)) { - in_esc = 1; - memmove(in_buff, in_buff + 1, len - i - 1); - len--; -@@ -271,7 +272,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len) - } - } - if (in_esc) { -- if (in_buff[i] == intf->session->sol_escape_char) { -+ if (in_buff[i] == intf->ssn_params.sol_escape_char) { - in_esc = 0; - i++; - continue; -@@ -280,23 +281,23 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len) - switch (in_buff[i]) { - case '.': - printf("%c. [terminated ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - return -1; - case 'Z' - 64: - printf("%c^Z [suspend ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - /* Restore tty back to raw */ - suspend_self(1); - break; - case 'X' - 64: - printf("%c^X [suspend ipmitool]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - /* Don't restore to raw mode */ - suspend_self(0); - break; - case '?': - printf("%c? [ipmitool help]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - print_escape_seq(intf); - break; - } -@@ -411,8 +412,10 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv) - print_tsol_usage(); - return 0; - } else { -+ lprintf(LOG_ERR, "Invalid tsol command: '%s'\n", -+ argv[i]); - print_tsol_usage(); -- return 0; -+ return (-1); - } - } - -@@ -422,25 +425,25 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv) - sin.sin_port = htons(port); - - sa_in = (struct sockaddr_in *)&intf->session->addr; -- result = inet_pton(AF_INET, (const char *)intf->session->hostname, -+ result = inet_pton(AF_INET, (const char *)intf->ssn_params.hostname, - &sa_in->sin_addr); - - if (result <= 0) { -- struct hostent *host = gethostbyname((const char *)intf->session->hostname); -+ struct hostent *host = gethostbyname((const char *)intf->ssn_params.hostname); - if (host == NULL ) { - lprintf(LOG_ERR, "Address lookup for %s failed", -- intf->session->hostname); -+ intf->ssn_params.hostname); - return -1; - } - if (host->h_addrtype != AF_INET) { - lprintf(LOG_ERR, - "Address lookup for %s failed. Got %s, expected IPv4 address.", -- intf->session->hostname, -+ intf->ssn_params.hostname, - (host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown"); - return (-1); - } - sa_in->sin_family = host->h_addrtype; -- memcpy(&sa_in->sin_addr, host->h_addr, host->h_length); -+ memcpy(&sa_in->sin_addr, host->h_addr_list[0], host->h_length); - } - - fd_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); -@@ -498,7 +501,7 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv) - } - - printf("[SOL Session operational. Use %c? for help]\n", -- intf->session->sol_escape_char); -+ intf->ssn_params.sol_escape_char); - - gettimeofday(&_start_keepalive, 0); - -diff --git a/lib/ipmi_user.c b/lib/ipmi_user.c -index d7e5890..6074209 100644 ---- a/lib/ipmi_user.c -+++ b/lib/ipmi_user.c -@@ -53,249 +53,293 @@ extern int verbose; - extern int csv_output; - - --#define IPMI_PASSWORD_DISABLE_USER 0x00 --#define IPMI_PASSWORD_ENABLE_USER 0x01 --#define IPMI_PASSWORD_SET_PASSWORD 0x02 --#define IPMI_PASSWORD_TEST_PASSWORD 0x03 -- --/* -- * ipmi_get_user_access -+/* _ipmi_get_user_access - Get User Access for given channel. Results are stored -+ * into passed struct. - * -- * param intf [in] -- * param channel_number [in] -- * param user_id [in] -- * param user_access [out] -+ * @intf - IPMI interface -+ * @user_access_rsp - ptr to user_access_t with UID and Channel set - * -- * return 0 on succes -- * 1 on failure -+ * returns - negative number means error, positive is a ccode - */ --static int --ipmi_get_user_access( -- struct ipmi_intf *intf, -- uint8_t channel_number, -- uint8_t user_id, -- struct user_access_rsp *user_access) -+int -+_ipmi_get_user_access(struct ipmi_intf *intf, -+ struct user_access_t *user_access_rsp) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t msg_data[2]; -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ -- req.msg.cmd = IPMI_GET_USER_ACCESS; /* 0x44 */ -- req.msg.data = msg_data; -+ struct ipmi_rq req = {0}; -+ struct ipmi_rs *rsp; -+ uint8_t data[2]; -+ if (user_access_rsp == NULL) { -+ return (-3); -+ } -+ data[0] = user_access_rsp->channel & 0x0F; -+ data[1] = user_access_rsp->user_id & 0x3F; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_USER_ACCESS; -+ req.msg.data = data; - req.msg.data_len = 2; -- -- -- /* The channel number will remain constant throughout this function */ -- msg_data[0] = channel_number; -- msg_data[1] = user_id; -- - rsp = intf->sendrecv(intf, &req); -- - if (rsp == NULL) { -- lprintf(LOG_ERR, "Get User Access command failed " -- "(channel %d, user %d)", channel_number, user_id); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Get User Access command failed " -- "(channel %d, user %d): %s", channel_number, user_id, -- val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ return (-1); -+ } else if (rsp->ccode != 0) { -+ return rsp->ccode; -+ } else if (rsp->data_len != 4) { -+ return (-2); - } -- -- memcpy(user_access, -- rsp->data, -- sizeof(struct user_access_rsp)); -- -- return 0; -+ user_access_rsp->max_user_ids = rsp->data[0] & 0x3F; -+ user_access_rsp->enable_status = rsp->data[1] & 0xC0; -+ user_access_rsp->enabled_user_ids = rsp->data[1] & 0x3F; -+ user_access_rsp->fixed_user_ids = rsp->data[2] & 0x3F; -+ user_access_rsp->callin_callback = rsp->data[3] & 0x40; -+ user_access_rsp->link_auth = rsp->data[3] & 0x20; -+ user_access_rsp->ipmi_messaging = rsp->data[3] & 0x10; -+ user_access_rsp->privilege_limit = rsp->data[3] & 0x0F; -+ return rsp->ccode; - } - -- -- --/* -- * ipmi_get_user_name -+/* _ipmi_get_user_name - Fetch User Name for given User ID. User Name is stored -+ * into passed structure. - * -- * param intf [in] -- * param channel_number [in] -- * param user_id [in] -- * param user_name [out] -+ * @intf - ipmi interface -+ * @user_name - user_name_t struct with UID set - * -- * return 0 on succes -- * 1 on failure -+ * returns - negative number means error, positive is a ccode - */ --static int --ipmi_get_user_name( -- struct ipmi_intf *intf, -- uint8_t user_id, -- char *user_name) -+int -+_ipmi_get_user_name(struct ipmi_intf *intf, struct user_name_t *user_name_ptr) - { -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t msg_data[1]; -- -- memset(user_name, 0, 17); -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ -- req.msg.cmd = IPMI_GET_USER_NAME; /* 0x45 */ -- req.msg.data = msg_data; -+ struct ipmi_rq req = {0}; -+ struct ipmi_rs *rsp; -+ uint8_t data[1]; -+ if (user_name_ptr == NULL) { -+ return (-3); -+ } -+ data[0] = user_name_ptr->user_id & 0x3F; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_USER_NAME; -+ req.msg.data = data; - req.msg.data_len = 1; -- -- msg_data[0] = user_id; -- - rsp = intf->sendrecv(intf, &req); -- - if (rsp == NULL) { -- lprintf(LOG_ERR, "Get User Name command failed (user %d)", -- user_id); -- return -1; -- } -- if (rsp->ccode > 0) { -- if (rsp->ccode == 0xcc) -- return 0; -- lprintf(LOG_ERR, "Get User Name command failed (user %d): %s", -- user_id, val2str(rsp->ccode, completion_code_vals)); -- return -1; -+ return (-1); -+ } else if (rsp->ccode > 0) { -+ return rsp->ccode; -+ } else if (rsp->data_len != 16) { -+ return (-2); - } -- -- memcpy(user_name, rsp->data, 16); -- -- return 0; -+ memset(user_name_ptr->user_name, '\0', 17); -+ memcpy(user_name_ptr->user_name, rsp->data, 16); -+ return rsp->ccode; - } - -+/* _ipmi_set_user_access - Set User Access for given channel. -+ * -+ * @intf - IPMI interface -+ * @user_access_req - ptr to user_access_t with desired User Access. -+ * @change_priv_limit_only - change User's privilege limit only -+ * -+ * returns - negative number means error, positive is a ccode -+ */ -+int -+_ipmi_set_user_access(struct ipmi_intf *intf, -+ struct user_access_t *user_access_req, -+ uint8_t change_priv_limit_only) -+{ -+ uint8_t data[4]; -+ struct ipmi_rq req = {0}; -+ struct ipmi_rs *rsp; -+ if (user_access_req == NULL) { -+ return (-3); -+ } -+ data[0] = change_priv_limit_only ? 0x00 : 0x80; -+ if (user_access_req->callin_callback) { -+ data[0] |= 0x40; -+ } -+ if (user_access_req->link_auth) { -+ data[0] |= 0x20; -+ } -+ if (user_access_req->ipmi_messaging) { -+ data[0] |= 0x10; -+ } -+ data[0] |= (user_access_req->channel & 0x0F); -+ data[1] = user_access_req->user_id & 0x3F; -+ data[2] = user_access_req->privilege_limit & 0x0F; -+ data[3] = user_access_req->session_limit & 0x0F; -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_SET_USER_ACCESS; -+ req.msg.data = data; -+ req.msg.data_len = 4; -+ rsp = intf->sendrecv(intf, &req); -+ if (rsp == NULL) { -+ return (-1); -+ } else { -+ return rsp->ccode; -+ } -+} - -+/* _ipmi_set_user_password - Set User Password command. -+ * -+ * @intf - IPMI interface -+ * @user_id - IPMI User ID -+ * @operation - which operation to perform(en/disable user, set/test password) -+ * @password - User Password -+ * @is_twenty_byte - 0 = store as 16byte, otherwise store as 20byte password -+ * -+ * returns - negative number means error, positive is a ccode -+ */ -+int -+_ipmi_set_user_password(struct ipmi_intf *intf, uint8_t user_id, -+ uint8_t operation, const char *password, -+ uint8_t is_twenty_byte) -+{ -+ struct ipmi_rq req = {0}; -+ struct ipmi_rs *rsp; -+ uint8_t *data; -+ uint8_t data_len = (is_twenty_byte) ? 22 : 18; -+ data = malloc(sizeof(uint8_t) * data_len); -+ if (data == NULL) { -+ return (-4); -+ } -+ memset(data, 0, data_len); -+ data[0] = (is_twenty_byte) ? 0x80 : 0x00; -+ data[0] |= (0x0F & user_id); -+ data[1] = 0x03 & operation; -+ if (password != NULL) { -+ size_t copy_len = strlen(password); -+ if (copy_len > (data_len - 2)) { -+ copy_len = data_len - 2; -+ } else if (copy_len < 1) { -+ copy_len = 0; -+ } -+ strncpy((char *)(data + 2), password, copy_len); -+ } - -+ req.msg.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_SET_USER_PASSWORD; -+ req.msg.data = data; -+ req.msg.data_len = data_len; -+ rsp = intf->sendrecv(intf, &req); -+ free(data); -+ data = NULL; -+ if (rsp == NULL) { -+ return (-1); -+ } -+ return rsp->ccode; -+} - - static void --dump_user_access( -- uint8_t user_id, -- const char * user_name, -- struct user_access_rsp * user_access) -+dump_user_access(const char *user_name, -+ struct user_access_t *user_access) - { - static int printed_header = 0; -- -- if (! printed_header) -- { -+ if (!printed_header) { - printf("ID Name Callin Link Auth IPMI Msg " -- "Channel Priv Limit\n"); -+ "Channel Priv Limit\n"); - printed_header = 1; - } -- - printf("%-4d%-17s%-8s%-11s%-11s%-s\n", -- user_id, -- user_name, -- user_access->no_callin_access? "false": "true ", -- user_access->link_auth_access? "true ": "false", -- user_access->ipmi_messaging_access? "true ": "false", -- val2str(user_access->channel_privilege_limit, -- ipmi_privlvl_vals)); -+ user_access->user_id, -+ user_name, -+ user_access->callin_callback? "false": "true ", -+ user_access->link_auth? "true ": "false", -+ user_access->ipmi_messaging? "true ": "false", -+ val2str(user_access->privilege_limit, -+ ipmi_privlvl_vals)); - } - - - - static void --dump_user_access_csv( -- uint8_t user_id, -- const char *user_name, -- struct user_access_rsp *user_access) -+dump_user_access_csv(const char *user_name, -+ struct user_access_t *user_access) - { - printf("%d,%s,%s,%s,%s,%s\n", -- user_id, -- user_name, -- user_access->no_callin_access? "false": "true", -- user_access->link_auth_access? "true": "false", -- user_access->ipmi_messaging_access? "true": "false", -- val2str(user_access->channel_privilege_limit, -- ipmi_privlvl_vals)); -+ user_access->user_id, -+ user_name, -+ user_access->callin_callback? "false": "true", -+ user_access->link_auth? "true": "false", -+ user_access->ipmi_messaging? "true": "false", -+ val2str(user_access->privilege_limit, -+ ipmi_privlvl_vals)); - } - -+/* ipmi_print_user_list - List IPMI Users and their ACLs for given channel. -+ * -+ * @intf - IPMI interface -+ * @channel_number - IPMI channel -+ * -+ * returns - 0 on success, (-1) on error -+ */ - static int --ipmi_print_user_list( -- struct ipmi_intf *intf, -- uint8_t channel_number) -+ipmi_print_user_list(struct ipmi_intf *intf, uint8_t channel_number) - { -- /* This is where you were! */ -- char user_name[17]; -- struct user_access_rsp user_access; -+ struct user_access_t user_access = {0}; -+ struct user_name_t user_name = {0}; -+ int ccode = 0; - uint8_t current_user_id = 1; -- -- -- do -- { -- if (ipmi_get_user_access(intf, -- channel_number, -- current_user_id, -- &user_access)) -- return -1; -- -- -- if (ipmi_get_user_name(intf, -- current_user_id, -- user_name)) -- return -1; -- -- if ((current_user_id == 0) || -- user_access.link_auth_access || -- user_access.ipmi_messaging_access || -- strcmp("", user_name)) -- { -- if (csv_output) -- dump_user_access_csv(current_user_id, -- user_name, &user_access); -- else -- dump_user_access(current_user_id, -- user_name, -- &user_access); -+ do { -+ memset(&user_access, 0, sizeof(user_access)); -+ user_access.user_id = current_user_id; -+ user_access.channel = channel_number; -+ ccode = _ipmi_get_user_access(intf, &user_access); -+ if (eval_ccode(ccode) != 0) { -+ return (-1); -+ } -+ memset(&user_name, 0, sizeof(user_name)); -+ user_name.user_id = current_user_id; -+ ccode = _ipmi_get_user_name(intf, &user_name); -+ if (ccode == 0xCC) { -+ user_name.user_id = current_user_id; -+ memset(&user_name.user_name, '\0', 17); -+ } else if (eval_ccode(ccode) != 0) { -+ return (-1); -+ } -+ if (csv_output) { -+ dump_user_access_csv((char *)user_name.user_name, -+ &user_access); -+ } else { -+ dump_user_access((char *)user_name.user_name, -+ &user_access); - } -- -- - ++current_user_id; -- } while((current_user_id <= user_access.maximum_ids) && -- (current_user_id <= IPMI_UID_MAX)); /* Absolute maximum allowed by spec */ -- -- -+ } while ((current_user_id <= user_access.max_user_ids) -+ && (current_user_id <= IPMI_UID_MAX)); - return 0; - } - -- -- -+/* ipmi_print_user_summary - print User statistics for given channel -+ * -+ * @intf - IPMI interface -+ * @channel_number - channel number -+ * -+ * returns - 0 on success, (-1) on error -+ */ - static int --ipmi_print_user_summary( -- struct ipmi_intf * intf, -- uint8_t channel_number) -+ipmi_print_user_summary(struct ipmi_intf *intf, uint8_t channel_number) - { -- struct user_access_rsp user_access; -- -- if (ipmi_get_user_access(intf, -- channel_number, -- 1, -- &user_access)) -- return -1; -- -- if (csv_output) -- { -- printf("%d,%d,%d\n", -- user_access.maximum_ids, -- user_access.enabled_user_count, -- user_access.fixed_name_count); -+ struct user_access_t user_access = {0}; -+ int ccode = 0; -+ user_access.channel = channel_number; -+ user_access.user_id = 1; -+ ccode = _ipmi_get_user_access(intf, &user_access); -+ if (eval_ccode(ccode) != 0) { -+ return (-1); - } -- else -- { -- printf("Maximum IDs : %d\n", -- user_access.maximum_ids); -- printf("Enabled User Count : %d\n", -- user_access.enabled_user_count); -- printf("Fixed Name Count : %d\n", -- user_access.fixed_name_count); -+ if (csv_output) { -+ printf("%" PRIu8 ",%" PRIu8 ",%" PRIu8 "\n", -+ user_access.max_user_ids, -+ user_access.enabled_user_ids, -+ user_access.fixed_user_ids); -+ } else { -+ printf("Maximum IDs : %" PRIu8 "\n", -+ user_access.max_user_ids); -+ printf("Enabled User Count : %" PRIu8 "\n", -+ user_access.enabled_user_ids); -+ printf("Fixed Name Count : %" PRIu8 "\n", -+ user_access.fixed_user_ids); - } -- - return 0; - } - -- -- - /* - * ipmi_user_set_username - */ -@@ -343,125 +387,17 @@ ipmi_user_set_username( - return 0; - } - --static int --ipmi_user_set_userpriv( -- struct ipmi_intf *intf, -- uint8_t channel, -- uint8_t user_id, -- const unsigned char privLevel) --{ -- struct ipmi_rs *rsp; -- struct ipmi_rq req; -- uint8_t msg_data[4] = {0, 0, 0, 0}; -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ -- req.msg.cmd = IPMI_SET_USER_ACCESS; /* 0x43 */ -- req.msg.data = msg_data; -- req.msg.data_len = 4; -- -- /* The channel number will remain constant throughout this function */ -- msg_data[0] = (channel & 0x0f); -- msg_data[1] = (user_id & 0x3f); -- msg_data[2] = (privLevel & 0x0f); -- msg_data[3] = 0; -- -- rsp = intf->sendrecv(intf, &req); -- -- if (rsp == NULL) -- { -- lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)", -- user_id); -- return -1; -- } -- if (rsp->ccode > 0) -- { -- lprintf(LOG_ERR, "Set Privilege Level command failed (user %d): %s", -- user_id, val2str(rsp->ccode, completion_code_vals)); -- return -1; -- } -- -- return 0; --} -- --/* -- * ipmi_user_set_password -- * -- * This function is responsible for 4 things -- * Enabling/Disabling users -- * Setting/Testing passwords -- */ --static int --ipmi_user_set_password( -- struct ipmi_intf * intf, -- uint8_t user_id, -- uint8_t operation, -- const char *password, -- int is_twenty_byte_password) --{ -- struct ipmi_rs * rsp; -- struct ipmi_rq req; -- uint8_t msg_data[22]; -- -- int password_length = (is_twenty_byte_password? 20 : 16); -- -- memset(&req, 0, sizeof(req)); -- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */ -- req.msg.cmd = IPMI_SET_USER_PASSWORD; /* 0x47 */ -- req.msg.data = msg_data; -- req.msg.data_len = password_length + 2; -- -- -- /* The channel number will remain constant throughout this function */ -- msg_data[0] = user_id; -- -- if (is_twenty_byte_password) -- msg_data[0] |= 0x80; -- -- msg_data[1] = operation; -- -- memset(msg_data + 2, 0, password_length); -- -- if (password != NULL) -- strncpy((char *)(msg_data + 2), password, password_length); -- -- rsp = intf->sendrecv(intf, &req); -- -- if (rsp == NULL) { -- lprintf(LOG_ERR, "Set User Password command failed (user %d)", -- user_id); -- return -1; -- } -- if (rsp->ccode > 0) { -- lprintf(LOG_ERR, "Set User Password command failed (user %d): %s", -- user_id, val2str(rsp->ccode, completion_code_vals)); -- return rsp->ccode; -- } -- -- return 0; --} -- -- -- --/* -- * ipmi_user_test_password -- * -- * Call ipmi_user_set_password, and interpret the result -+/* ipmi_user_test_password - Call _ipmi_set_user_password() with operation bit -+ * set to test password and interpret result. - */ - static int --ipmi_user_test_password( -- struct ipmi_intf * intf, -- uint8_t user_id, -- const char * password, -- int is_twenty_byte_password) -+ipmi_user_test_password(struct ipmi_intf *intf, uint8_t user_id, -+ const char *password, uint8_t is_twenty_byte_password) - { -- int ret; -- -- ret = ipmi_user_set_password(intf, -- user_id, -- IPMI_PASSWORD_TEST_PASSWORD, -- password, -- is_twenty_byte_password); -+ int ret = 0; -+ ret = _ipmi_set_user_password(intf, user_id, -+ IPMI_PASSWORD_TEST_PASSWORD, password, -+ is_twenty_byte_password); - - switch (ret) { - case 0: -@@ -487,16 +423,40 @@ ipmi_user_test_password( - static void - print_user_usage(void) - { -- lprintf(LOG_NOTICE, "User Commands:"); -- lprintf(LOG_NOTICE, " summary []"); -- lprintf(LOG_NOTICE, " list []"); -- lprintf(LOG_NOTICE, " set name "); -- lprintf(LOG_NOTICE, " set password []"); -- lprintf(LOG_NOTICE, " disable "); -- lprintf(LOG_NOTICE, " enable "); - lprintf(LOG_NOTICE, -- " priv []"); -- lprintf(LOG_NOTICE, " test <16|20> [\n"); -+"User Commands:"); -+ lprintf(LOG_NOTICE, -+" summary []"); -+ lprintf(LOG_NOTICE, -+" list []"); -+ lprintf(LOG_NOTICE, -+" set name "); -+ lprintf(LOG_NOTICE, -+" set password [ <16|20>]"); -+ lprintf(LOG_NOTICE, -+" disable "); -+ lprintf(LOG_NOTICE, -+" enable "); -+ lprintf(LOG_NOTICE, -+" priv []"); -+ lprintf(LOG_NOTICE, -+" Privilege levels:"); -+ lprintf(LOG_NOTICE, -+" * 0x1 - Callback"); -+ lprintf(LOG_NOTICE, -+" * 0x2 - User"); -+ lprintf(LOG_NOTICE, -+" * 0x3 - Operator"); -+ lprintf(LOG_NOTICE, -+" * 0x4 - Administrator"); -+ lprintf(LOG_NOTICE, -+" * 0x5 - OEM Proprietary"); -+ lprintf(LOG_NOTICE, -+" * 0xF - No Access"); -+ lprintf(LOG_NOTICE, ""); -+ lprintf(LOG_NOTICE, -+" test <16|20> ["); -+ lprintf(LOG_NOTICE, ""); - } - - -@@ -509,328 +469,282 @@ ipmi_user_build_password_prompt(uint8_t user_id) - return prompt; - } - -- --/* -- * ipmi_user_main -+/* ask_password - ask user for password - * -- * Upon entry to this function argv should contain our arguments -- * specific to this subcommand -+ * @user_id: User ID which will be built-in into text -+ * -+ * @returns pointer to char with password - */ --int --ipmi_user_main(struct ipmi_intf * intf, int argc, char ** argv) -+char * -+ask_password(uint8_t user_id) - { -- int retval = 0; -+ const char *password_prompt = -+ ipmi_user_build_password_prompt(user_id); -+# ifdef HAVE_GETPASSPHRASE -+ return getpassphrase(password_prompt); -+# else -+ return (char*)getpass(password_prompt); -+# endif -+} - -- /* -- * Help -- */ -- if (argc == 0 || strncmp(argv[0], "help", 4) == 0) -- { -+int -+ipmi_user_summary(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* Summary*/ -+ uint8_t channel; -+ if (argc == 1) { -+ channel = 0x0E; /* Ask about the current channel */ -+ } else if (argc == 2) { -+ if (is_ipmi_channel_num(argv[1], &channel) != 0) { -+ return (-1); -+ } -+ } else { - print_user_usage(); -+ return (-1); - } -+ return ipmi_print_user_summary(intf, channel); -+} - -- /* -- * Summary -- */ -- else if (strncmp(argv[0], "summary", 7) == 0) -- { -- uint8_t channel; -- -- if (argc == 1) -- channel = 0x0E; /* Ask about the current channel */ -- else if (argc == 2) -- { -- if (str2uchar(argv[1], &channel) != 0) -- { -- lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); -- return (-1); -- } -- } -- else -- { -- print_user_usage(); -- return -1; -+int -+ipmi_user_list(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* List */ -+ uint8_t channel; -+ if (argc == 1) { -+ channel = 0x0E; /* Ask about the current channel */ -+ } else if (argc == 2) { -+ if (is_ipmi_channel_num(argv[1], &channel) != 0) { -+ return (-1); - } -- -- retval = ipmi_print_user_summary(intf, channel); -+ } else { -+ print_user_usage(); -+ return (-1); - } -+ return ipmi_print_user_list(intf, channel); -+} - -- -- /* -- * List -- */ -- else if (strncmp(argv[0], "list", 4) == 0) -- { -- uint8_t channel; -- -- if (argc == 1) -- channel = 0x0E; /* Ask about the current channel */ -- else if (argc == 2) -- { -- if (str2uchar(argv[1], &channel) != 0) -- { -- lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); -- return (-1); -- } -- } -- else -- { -- print_user_usage(); -- return -1; -+int -+ipmi_user_test(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* Test */ -+ char *password = NULL; -+ int password_length = 0; -+ uint8_t user_id = 0; -+ /* a little irritating, isn't it */ -+ if (argc != 3 && argc != 4) { -+ print_user_usage(); -+ return (-1); -+ } -+ if (is_ipmi_user_id(argv[1], &user_id)) { -+ return (-1); -+ } -+ if (str2int(argv[2], &password_length) != 0 -+ || (password_length != 16 && password_length != 20)) { -+ lprintf(LOG_ERR, -+ "Given password length '%s' is invalid.", -+ argv[2]); -+ lprintf(LOG_ERR, "Expected value is either 16 or 20."); -+ return (-1); -+ } -+ if (argc == 3) { -+ /* We need to prompt for a password */ -+ password = ask_password(user_id); -+ if (password == NULL) { -+ lprintf(LOG_ERR, "ipmitool: malloc failure"); -+ return (-1); - } -- -- retval = ipmi_print_user_list(intf, channel); -+ } else { -+ password = argv[3]; - } -+ return ipmi_user_test_password(intf, -+ user_id, -+ password, -+ password_length == 20); -+} - -+int -+ipmi_user_priv(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ struct user_access_t user_access = {0}; -+ int ccode = 0; - -- -- /* -- * Test -- */ -- else if (strncmp(argv[0], "test", 4) == 0) -- { -- // a little irritating, isn't it -- if (argc == 3 || argc == 4) -- { -- char * password = NULL; -- int password_length = 0; -- uint8_t user_id = 0; -- if (is_ipmi_user_id(argv[1], &user_id)) { -- return (-1); -- } -- if (str2int(argv[2], &password_length) != 0 -- || (password_length != 16 && password_length != 20)) { -- lprintf(LOG_ERR, -- "Given password length '%s' is invalid.", -- argv[2]); -- lprintf(LOG_ERR, "Expected value is either 16 or 20."); -- return (-1); -- } -- -- if (argc == 3) -- { -- /* We need to prompt for a password */ -- -- char * tmp; -- const char * password_prompt = -- ipmi_user_build_password_prompt(user_id); --# ifdef HAVE_GETPASSPHRASE -- tmp = getpassphrase (password_prompt); --# else -- tmp = (char*)getpass (password_prompt); --# endif -- if (tmp != NULL) { -- password = strdup(tmp); -- tmp = NULL; -- } -- if (password == NULL) { -- lprintf(LOG_ERR, "ipmitool: malloc failure"); -- return -1; -- } -- } -- else { -- password = strdup(argv[3]); -- } -- -- -- retval = ipmi_user_test_password(intf, -- user_id, -- password, -- password_length == 20); -- if (password != NULL) { -- free(password); -- password = NULL; -- } -- } -- else -- { -- print_user_usage(); -- return -1; -+ if (argc != 3 && argc != 4) { -+ print_user_usage(); -+ return (-1); -+ } -+ if (argc == 4) { -+ if (is_ipmi_channel_num(argv[3], &user_access.channel) != 0) { -+ return (-1); - } -+ } else { -+ /* Use channel running on */ -+ user_access.channel = 0x0E; - } -+ if (is_ipmi_user_priv_limit(argv[2], &user_access.privilege_limit) != 0 -+ || is_ipmi_user_id(argv[1], &user_access.user_id) != 0) { -+ return (-1); -+ } -+ ccode = _ipmi_set_user_access(intf, &user_access, 1); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)", -+ user_access.user_id); -+ return (-1); -+ } else { -+ printf("Set Privilege Level command successful (user %d)", -+ user_access.user_id); -+ return 0; -+ } -+} - -- /* -- * Set -- */ -- else if (strncmp(argv[0], "set", 3) == 0) -- { -- /* -- * Set Password -- */ -- if ((argc >= 3) && -- (strncmp("password", argv[1], 8) == 0)) -- { -- char * password = NULL; -- uint8_t user_id = 0; -- if (is_ipmi_user_id(argv[2], &user_id)) { -- return (-1); -- } -- -- if (argc == 3) -- { -- /* We need to prompt for a password */ -- char * tmp; -- const char * password_prompt = -- ipmi_user_build_password_prompt(user_id); --# ifdef HAVE_GETPASSPHRASE -- tmp = getpassphrase (password_prompt); --# else -- tmp = (char*)getpass (password_prompt); --# endif -- if (tmp != NULL) { -- password = strdup(tmp); -- tmp = NULL; -- } -- if (password == NULL) { -- lprintf(LOG_ERR, "ipmitool: malloc failure"); -- return -1; -- } --# ifdef HAVE_GETPASSPHRASE -- tmp = getpassphrase (password_prompt); --# else -- tmp = (char*)getpass (password_prompt); --# endif -- if (tmp == NULL) { -- lprintf(LOG_ERR, "ipmitool: malloc failure"); -- return (-1); -- } -- if (strlen(password) != strlen(tmp) -- || strncmp(password, tmp, strlen(tmp))) { -- lprintf(LOG_ERR, "Passwords do not match."); -- free(password); -- password = NULL; -- return -1; -- } -- tmp = NULL; -- } else { -- password = strdup(argv[3]); -- } -- -- if (password == NULL) { -- lprintf(LOG_ERR, "Unable to parse password argument."); -- return -1; -- } -- else if (strlen(password) > 20) -- { -- lprintf(LOG_ERR, "Password is too long (> 20 bytes)"); -- return -1; -- } -+int -+ipmi_user_mod(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* Disable / Enable */ -+ uint8_t user_id; -+ uint8_t operation; - -- retval = ipmi_user_set_password(intf, -- user_id, -- IPMI_PASSWORD_SET_PASSWORD, -- password, -- strlen(password) > 16); -- if (password != NULL) { -- free(password); -- password = NULL; -- } -- } -+ if (argc != 2) { -+ print_user_usage(); -+ return (-1); -+ } -+ if (is_ipmi_user_id(argv[1], &user_id)) { -+ return (-1); -+ } -+ operation = (strncmp(argv[0], "disable", 7) == 0) ? -+ IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER; - -- /* -- * Set Name -- */ -- else if ((argc >= 2) && -- (strncmp("name", argv[1], 4) == 0)) -- { -- uint8_t user_id = 0; -- if (argc != 4) -- { -- print_user_usage(); -- return -1; -- } -- if (is_ipmi_user_id(argv[2], &user_id)) { -- return (-1); -- } -+ return _ipmi_set_user_password(intf, user_id, operation, -+ (char *)NULL, 0); -+} - -- if (strlen(argv[3]) > 16) -- { -- lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); -- return -1; -- } -+int -+ipmi_user_password(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ char *password = NULL; -+ int ccode = 0; -+ uint8_t password_type = 16; -+ uint8_t user_id = 0; -+ if (is_ipmi_user_id(argv[2], &user_id)) { -+ return (-1); -+ } - -- retval = ipmi_user_set_username(intf, user_id, argv[3]); -+ if (argc == 3) { -+ /* We need to prompt for a password */ -+ char *tmp; -+ password = ask_password(user_id); -+ if (password == NULL) { -+ lprintf(LOG_ERR, "ipmitool: malloc failure"); -+ return (-1); - } -- else -- { -- print_user_usage(); -- return -1; -+ tmp = ask_password(user_id); -+ if (tmp == NULL) { -+ lprintf(LOG_ERR, "ipmitool: malloc failure"); -+ return (-1); - } -- } -- -- else if (strncmp(argv[0], "priv", 4) == 0) -- { -- uint8_t user_id; -- uint8_t priv_level; -- uint8_t channel = 0x0e; /* Use channel running on */ -- -- if (argc != 3 && argc != 4) -- { -- print_user_usage(); -- return -1; -+ if (strlen(password) != strlen(tmp) -+ || strncmp(password, tmp, strlen(tmp))) { -+ lprintf(LOG_ERR, "Passwords do not match."); -+ return (-1); - } -- -- if (argc == 4) -- { -- if (str2uchar(argv[3], &channel) != 0) -- { -- lprintf(LOG_ERR, "Invalid channel: %s", argv[3]); -+ } else { -+ password = argv[3]; -+ if (argc > 4) { -+ if ((str2uchar(argv[4], &password_type) != 0) -+ || (password_type != 16 && password_type != 20)) { -+ lprintf(LOG_ERR, "Invalid password length '%s'", argv[4]); - return (-1); - } -- channel = (channel & 0x0f); -+ } else { -+ password_type = 16; - } -- -- if (str2uchar(argv[2], &priv_level) != 0) -- { -- lprintf(LOG_ERR, "Invalid privilege level: %s", argv[2]); -- return (-1); -- } -- priv_level = (priv_level & 0x0f); -+ } - -- if (is_ipmi_user_id(argv[1], &user_id)) { -- return (-1); -- } -+ if (password == NULL) { -+ lprintf(LOG_ERR, "Unable to parse password argument."); -+ return (-1); -+ } else if (strlen(password) > 20) { -+ lprintf(LOG_ERR, "Password is too long (> 20 bytes)"); -+ return (-1); -+ } - -- retval = ipmi_user_set_userpriv(intf,channel,user_id,priv_level); -+ ccode = _ipmi_set_user_password(intf, user_id, -+ IPMI_PASSWORD_SET_PASSWORD, password, -+ password_type > 16); -+ if (eval_ccode(ccode) != 0) { -+ lprintf(LOG_ERR, "Set User Password command failed (user %d)", -+ user_id); -+ return (-1); -+ } else { -+ printf("Set User Password command successful (user %d)\n", -+ user_id); -+ return 0; - } -+} - -- /* -- * Disable / Enable -- */ -- else if ((strncmp(argv[0], "disable", 7) == 0) || -- (strncmp(argv[0], "enable", 6) == 0)) -- { -- uint8_t user_id; -- uint8_t operation; -- char null_password[16]; /* Not used, but required */ -+int -+ipmi_user_name(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* Set Name */ -+ uint8_t user_id = 0; -+ if (argc != 4) { -+ print_user_usage(); -+ return (-1); -+ } -+ if (is_ipmi_user_id(argv[2], &user_id)) { -+ return (-1); -+ } -+ if (strlen(argv[3]) > 16) { -+ lprintf(LOG_ERR, "Username is too long (> 16 bytes)"); -+ return (-1); -+ } - -- memset(null_password, 0, sizeof(null_password)); -+ return ipmi_user_set_username(intf, user_id, argv[3]); -+} - -- if (argc != 2) -- { -+/* -+ * ipmi_user_main -+ * -+ * Upon entry to this function argv should contain our arguments -+ * specific to this subcommand -+ */ -+int -+ipmi_user_main(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ if (argc == 0) { -+ lprintf(LOG_ERR, "Not enough parameters given."); -+ print_user_usage(); -+ return (-1); -+ } -+ if (strncmp(argv[0], "help", 4) == 0) { -+ /* Help */ -+ print_user_usage(); -+ return 0; -+ } else if (strncmp(argv[0], "summary", 7) == 0) { -+ return ipmi_user_summary(intf, argc, argv); -+ } else if (strncmp(argv[0], "list", 4) == 0) { -+ return ipmi_user_list(intf, argc, argv); -+ } else if (strncmp(argv[0], "test", 4) == 0) { -+ return ipmi_user_test(intf, argc, argv); -+ } else if (strncmp(argv[0], "set", 3) == 0) { -+ /* Set */ -+ if ((argc >= 3) -+ && (strncmp("password", argv[1], 8) == 0)) { -+ return ipmi_user_password(intf, argc, argv); -+ } else if ((argc >= 2) -+ && (strncmp("name", argv[1], 4) == 0)) { -+ return ipmi_user_name(intf, argc, argv); -+ } else { - print_user_usage(); -- return -1; -- } -- -- if (is_ipmi_user_id(argv[1], &user_id)) { - return (-1); - } -- -- operation = (strncmp(argv[0], "disable", 7) == 0) ? -- IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER; -- -- retval = ipmi_user_set_password(intf, -- user_id, -- operation, -- null_password, -- 0); /* This field is ignored */ -- } -- else -- { -- retval = -1; -+ } else if (strncmp(argv[0], "priv", 4) == 0) { -+ return ipmi_user_priv(intf, argc, argv); -+ } else if ((strncmp(argv[0], "disable", 7) == 0) -+ || (strncmp(argv[0], "enable", 6) == 0)) { -+ return ipmi_user_mod(intf, argc, argv); -+ } else { - lprintf(LOG_ERR, "Invalid user command: '%s'\n", argv[0]); - print_user_usage(); -+ return (-1); - } -- -- return retval; - } -diff --git a/lib/ipmi_vita.c b/lib/ipmi_vita.c -new file mode 100644 -index 0000000..45ddd3e ---- /dev/null -+++ b/lib/ipmi_vita.c -@@ -0,0 +1,1012 @@ -+/* -+ * Copyright (c) 2014 Pigeon Point Systems. 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 Pigeon Point Systems, or the names of -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * This software is provided "AS IS, " without a warranty of any kind. -+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, -+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. -+ * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE -+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING -+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL -+ * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, -+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR -+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF -+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, -+ * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Handled VITA 46.11 commands */ -+#define VITA_CMD_HELP 0 -+#define VITA_CMD_PROPERTIES 1 -+#define VITA_CMD_FRUCONTROL 2 -+#define VITA_CMD_ADDRINFO 3 -+#define VITA_CMD_ACTIVATE 4 -+#define VITA_CMD_DEACTIVATE 5 -+#define VITA_CMD_POLICY_GET 6 -+#define VITA_CMD_POLICY_SET 7 -+#define VITA_CMD_LED_PROP 8 -+#define VITA_CMD_LED_CAP 9 -+#define VITA_CMD_LED_GET 10 -+#define VITA_CMD_LED_SET 11 -+#define VITA_CMD_UNKNOWN 255 -+ -+/* VITA 46.11 Site Type strings */ -+static struct valstr vita_site_types[] = { -+ { VITA_FRONT_VPX_MODULE, "Front Loading VPX Plug-In Module" }, -+ { VITA_POWER_ENTRY, "Power Entry Module" }, -+ { VITA_CHASSIS_FRU, "Chassic FRU Information Module" }, -+ { VITA_DEDICATED_CHMC, "Dedicated Chassis Manager" }, -+ { VITA_FAN_TRAY, "Fan Tray" }, -+ { VITA_FAN_TRAY_FILTER, "Fan Tray Filter" }, -+ { VITA_ALARM_PANEL, "Alarm Panel" }, -+ { VITA_XMC, "XMC" }, -+ { VITA_VPX_RTM, "VPX Rear Transition Module" }, -+ { VITA_FRONT_VME_MODULE, "Front Loading VME Plug-In Module" }, -+ { VITA_FRONT_VXS_MODULE, "Front Loading VXS Plug-In Module" }, -+ { VITA_POWER_SUPPLY, "Power Supply" }, -+ { VITA_FRONT_VITA62_MODULE, "Front Loading VITA 62 Module\n" }, -+ { VITA_71_MODULE, "VITA 71 Module\n" }, -+ { VITA_FMC, "FMC\n" }, -+ { 0, NULL } -+}; -+ -+/* VITA 46.11 command help strings */ -+static struct valstr vita_help_strings[] = { -+ { -+ VITA_CMD_HELP, -+ "VITA commands:\n" -+ " properties - get VSO properties\n" -+ " frucontrol - FRU control\n" -+ " addrinfo - get address information\n" -+ " activate - activate a FRU\n" -+ " deactivate - deactivate a FRU\n" -+ " policy get - get the FRU activation policy\n" -+ " policy set - set the FRU activation policy\n" -+ " led prop - get led properties\n" -+ " led cap - get led color capabilities\n" -+ " led get - get led state\n" -+ " led set - set led state" -+ }, -+ { -+ VITA_CMD_FRUCONTROL, -+ "usage: frucontrol