diff --git a/0001-Incorporate-upstream-comments-to-289-add-whitespace.patch b/0001-Incorporate-upstream-comments-to-289-add-whitespace.patch index 47a7211..fb2fa55 100644 --- a/0001-Incorporate-upstream-comments-to-289-add-whitespace.patch +++ b/0001-Incorporate-upstream-comments-to-289-add-whitespace.patch @@ -8,10 +8,10 @@ Subject: [PATCH] Incorporate upstream comments to #289, add whitespace, other contrib/bmc-snmp-proxy | 130 +++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 54 deletions(-) -diff --git a/contrib/bmc-snmp-proxy b/contrib/bmc-snmp-proxy -index 1704ef3..98479b9 100644 ---- a/contrib/bmc-snmp-proxy -+++ b/contrib/bmc-snmp-proxy +Index: ipmitool-1.8.15/contrib/bmc-snmp-proxy +=================================================================== +--- ipmitool-1.8.15.orig/contrib/bmc-snmp-proxy 2015-01-14 14:34:05.488699284 +0100 ++++ ipmitool-1.8.15/contrib/bmc-snmp-proxy 2015-01-14 14:34:05.508699284 +0100 @@ -3,7 +3,7 @@ # # bmc-snmp-proxy: Set SNMP proxy to BMC (Baseboard Management Controller) @@ -21,7 +21,7 @@ index 1704ef3..98479b9 100644 # # Authors: Charles Rose # Jordan Hargrave -@@ -20,9 +20,9 @@ +@@ -24,9 +24,9 @@ SYSCONF_DIR="/etc/sysconfig" CONFIG="${SYSCONF_DIR}/bmc-snmp-proxy" @@ -34,7 +34,7 @@ index 1704ef3..98479b9 100644 TRAPD_CONF="/etc/snmp/snmptrapd.conf" -@@ -57,14 +57,16 @@ bmc_info_exists() +@@ -61,14 +61,16 @@ else RETVAL=2 fi @@ -52,7 +52,7 @@ index 1704ef3..98479b9 100644 return $RETVAL } -@@ -77,11 +79,12 @@ write_snmp_conf() +@@ -81,11 +83,12 @@ printf "###############################################\n" printf "# Automatically created by %s #\n" "${SCRIPT_NAME}" printf "###############################################\n" @@ -70,7 +70,7 @@ index 1704ef3..98479b9 100644 printf "###############################################\n" } -@@ -92,6 +95,7 @@ valid_ip() +@@ -96,6 +99,7 @@ printf -- "%s" "${1}"| grep -Eq \ "^${octet}\\.${octet}\\.${octet}\\.${octet}$" @@ -78,7 +78,7 @@ index 1704ef3..98479b9 100644 return $? } -@@ -112,37 +116,38 @@ set_snmp_proxy() +@@ -116,37 +120,38 @@ if check_vars; then PROXY_TOKEN="-c ${BMC_COMMUNITY} ${BMC_IPv4} ${BMC_OID}" @@ -132,7 +132,7 @@ index 1704ef3..98479b9 100644 fi } ############################################################################# -@@ -152,6 +157,7 @@ disable_snmp_proxy() +@@ -156,6 +161,7 @@ pick_alert_dest() { test_ip="$1" @@ -140,7 +140,7 @@ index 1704ef3..98479b9 100644 for ALERT_DEST in `seq 1 4` do temp_ip=$(${IPMITOOL} lan alert print ${CHANNEL} ${ALERT_DEST}\ -@@ -165,12 +171,12 @@ pick_alert_dest() +@@ -169,12 +175,12 @@ set_alert_dest_ip() { ${IPMITOOL} lan alert set ${CHANNEL} ${ALERT_DEST} ipaddr ${1} \ @@ -156,7 +156,7 @@ index 1704ef3..98479b9 100644 # Pick the first active LAN channel for CHANNEL in `seq 1 14` do -@@ -180,12 +186,12 @@ bmc_alert_dest() +@@ -184,12 +190,12 @@ # If TRAPD_IP is already set as an alert dest, if pick_alert_dest "${TRAPD_IP}"; then @@ -172,7 +172,7 @@ index 1704ef3..98479b9 100644 return $RETVAL # set: the TRAPD_IP set_alert_dest_ip "${TRAPD_IP}" -@@ -193,42 +199,54 @@ bmc_alert_dest() +@@ -197,42 +203,54 @@ # No free alert destinations RETVAL=9 fi @@ -236,7 +236,7 @@ index 1704ef3..98479b9 100644 printf "###############################################\n" } -@@ -236,10 +254,9 @@ config_trapd() +@@ -240,10 +258,9 @@ { # Proceed only if snmptrapd is available on the system if [ -f ${TRAPD_CONF} ]; then @@ -249,7 +249,7 @@ index 1704ef3..98479b9 100644 fi } -@@ -249,6 +266,7 @@ trap_sink_exists() +@@ -253,6 +270,7 @@ # multiple FORWARD_HOST=$(awk '/^trap.*sink/{print $2}; /^informsink/{print $2}' \ /etc/snmp/snmpd*conf | head -1) @@ -257,7 +257,7 @@ index 1704ef3..98479b9 100644 if [ -z "${FORWARD_HOST}" ]; then # there is no trapsink setup. return 1 -@@ -261,19 +279,20 @@ trap_sink_exists() +@@ -265,19 +283,20 @@ trap_forward() { NO_TRAP=0 @@ -283,7 +283,7 @@ index 1704ef3..98479b9 100644 else NO_TRAP=1 fi -@@ -288,7 +307,6 @@ service_reload() +@@ -292,7 +311,6 @@ service $1 reload [ $? -ne 0 ] && RETVAL=6 fi @@ -291,7 +291,7 @@ index 1704ef3..98479b9 100644 } ############################################################################# -@@ -296,11 +314,12 @@ start() +@@ -300,11 +318,12 @@ { if bmc_info_exists && check_snmp; then touch ${LOCKFILE} @@ -305,7 +305,7 @@ index 1704ef3..98479b9 100644 [ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \ service_reload snmptrapd fi -@@ -316,10 +335,11 @@ stop() +@@ -320,10 +339,11 @@ [ $RETVAL -eq 0 ] && service_reload snmpd if [ "${TRAP_FORWARD}" = "yes" ]; then @@ -318,7 +318,7 @@ index 1704ef3..98479b9 100644 rm -f ${LOCKFILE} fi } -@@ -329,12 +349,13 @@ status() +@@ -333,12 +353,13 @@ { eval_gettext "${SCRIPT_NAME}: snmp proxy to BMC is " # Checking for lockfile is better. @@ -333,7 +333,7 @@ index 1704ef3..98479b9 100644 echo RETVAL=0 } -@@ -360,10 +381,10 @@ case "$RETVAL" in +@@ -364,10 +385,10 @@ 0|1) ;; 2) eval_gettext "${SCRIPT_NAME}: failed to read ${BMC_INFO} " 1>&2 ;; 3) eval_gettext "${SCRIPT_NAME}: failed to get proxy config." 1>&2 ;; @@ -346,7 +346,7 @@ index 1704ef3..98479b9 100644 8) eval_gettext "${SCRIPT_NAME}: failed to set IPMI alert dest." 1>&2 ;; 9) eval_gettext "${SCRIPT_NAME}: no free IPMI alert dest." 1>&2 ;; 10) eval_gettext "${SCRIPT_NAME}: failed to set IPMI PEF." 1>&2 ;; -@@ -375,6 +396,7 @@ esac +@@ -379,6 +400,7 @@ if [ ${RETVAL} -gt 1 ]; then eval_gettext " Return code: ${RETVAL}"; echo fi @@ -354,6 +354,3 @@ index 1704ef3..98479b9 100644 exit ${RETVAL} ############################################################################# # end of file --- -1.8.3.1 - diff --git a/automake-1.13.patch b/automake-1.13.patch deleted file mode 100644 index a57bb11..0000000 --- a/automake-1.13.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: ipmitool-1.8.13/configure.in -=================================================================== ---- ipmitool-1.8.13.orig/configure.in -+++ ipmitool-1.8.13/configure.in -@@ -4,7 +4,7 @@ dnl - AC_INIT([src/ipmitool.c]) - AC_CANONICAL_SYSTEM - AM_INIT_AUTOMAKE([ipmitool], [1.8.13-cvs]) --AM_CONFIG_HEADER(config.h) -+AC_CONFIG_HEADER(config.h) - AC_CONFIG_SRCDIR([src/ipmitool.c]) - AC_PREREQ(2.50) - AC_SUBST(ac_configure_args) diff --git a/fix_file_permissions.patch b/fix_file_permissions.patch index a7e08a1..3ad2009 100644 --- a/fix_file_permissions.patch +++ b/fix_file_permissions.patch @@ -1,8 +1,8 @@ -Index: ipmitool-1.8.13/lib/helper.c +Index: ipmitool-1.8.15/lib/helper.c =================================================================== ---- ipmitool-1.8.13.orig/lib/helper.c -+++ ipmitool-1.8.13/lib/helper.c -@@ -657,7 +657,6 @@ ipmi_start_daemon(struct ipmi_intf *intf +--- 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 @@ #endif chdir("/"); @@ -10,11 +10,11 @@ Index: ipmitool-1.8.13/lib/helper.c for (fd=0; fd<64; fd++) { if (fd != intf->fd) -Index: ipmitool-1.8.13/src/ipmievd.c +Index: ipmitool-1.8.15/src/ipmievd.c =================================================================== ---- ipmitool-1.8.13.orig/src/ipmievd.c -+++ ipmitool-1.8.13/src/ipmievd.c -@@ -700,6 +700,7 @@ ipmievd_main(struct ipmi_event_intf * ei +--- 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 @@ int i, rc; int daemon = 1; struct sigaction act; @@ -22,7 +22,7 @@ Index: ipmitool-1.8.13/src/ipmievd.c memset(pidfile, 0, 64); sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum); -@@ -761,8 +762,9 @@ ipmievd_main(struct ipmi_event_intf * ei +@@ -762,8 +763,9 @@ ipmi_start_daemon(eintf->intf); diff --git a/fwum_enhance_output.patch b/fwum_enhance_output.patch index f4b918e..1b22e3a 100644 --- a/fwum_enhance_output.patch +++ b/fwum_enhance_output.patch @@ -1,8 +1,8 @@ -Index: ipmitool-1.8.13/lib/ipmi_fwum.c +Index: ipmitool-1.8.15/lib/ipmi_fwum.c =================================================================== ---- ipmitool-1.8.13.orig/lib/ipmi_fwum.c -+++ ipmitool-1.8.13/lib/ipmi_fwum.c -@@ -1102,12 +1102,14 @@ ipmi_kfwum_checkfwcompat(tKFWUM_BoardInf +--- 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 @@ int compatible = 0; if (boardInfo.iana != firmInfo.iana) { lprintf(LOG_ERR, @@ -19,7 +19,7 @@ Index: ipmitool-1.8.13/lib/ipmi_fwum.c compatible = (-1); } if (compatible != 0) { -@@ -1125,6 +1127,10 @@ printf_kfwum_info(tKFWUM_BoardInfo board +@@ -1122,6 +1124,10 @@ printf( "Target IANA number : %u\n", boardInfo.iana); printf( diff --git a/ipmitool-1.8.10-implicit-fortify-decl.patch b/ipmitool-1.8.10-implicit-fortify-decl.patch index ccce7b4..791bedc 100644 --- a/ipmitool-1.8.10-implicit-fortify-decl.patch +++ b/ipmitool-1.8.10-implicit-fortify-decl.patch @@ -6,8 +6,8 @@ forwardported from 1.8.10 to 1.8.11. Index: lib/ipmi_sdradd.c =================================================================== ---- lib/ipmi_sdradd.c.orig -+++ lib/ipmi_sdradd.c +--- lib/ipmi_sdradd.c.orig 2015-01-14 15:38:00.728760259 +0100 ++++ lib/ipmi_sdradd.c 2015-01-14 15:38:11.500760430 +0100 @@ -38,6 +38,7 @@ #include #include @@ -18,8 +18,8 @@ Index: lib/ipmi_sdradd.c #include Index: lib/ipmi_hpmfwupg.c =================================================================== ---- lib/ipmi_hpmfwupg.c.orig -+++ lib/ipmi_hpmfwupg.c +--- lib/ipmi_hpmfwupg.c.orig 2015-01-14 15:38:00.728760259 +0100 ++++ lib/ipmi_hpmfwupg.c 2015-01-14 15:38:11.504760430 +0100 @@ -40,6 +40,8 @@ #include "../src/plugins/lan/md5.h" #include @@ -29,15 +29,24 @@ Index: lib/ipmi_hpmfwupg.c #include #if HAVE_CONFIG_H -Index: configure.in +Index: configure.ac =================================================================== ---- configure.in.orig -+++ configure.in -@@ -25,6 +25,7 @@ AC_CHECK_HEADERS([sys/byteorder.h bytesw +--- configure.ac.orig 2015-01-14 15:38:00.728760259 +0100 ++++ configure.ac 2015-01-14 16:29:03.744808956 +0100 +@@ -25,6 +25,7 @@ AC_C_CONST AC_C_INLINE AC_C_BIGENDIAN +AC_GNU_SOURCE - AC_FUNC_MALLOC AC_FUNC_SELECT_ARGTYPES + AC_FUNC_STRTOD +@@ -32,7 +33,7 @@ + AC_CHECK_FUNCS([memmove memset strchr strdup strerror]) + AC_CHECK_FUNCS([getpassphrase]) + +-CFLAGS="$CFLAGS -Wall -Wextra -std=c99 -pedantic -Wformat -Wformat-nonliteral" ++CFLAGS="$CFLAGS -fno-strict-aliasing -Wreturn-type -std=c99" + + AM_PROG_LIBTOOL + LIBTOOL="$LIBTOOL --silent" diff --git a/ipmitool-1.8.13.tar.bz2 b/ipmitool-1.8.13.tar.bz2 deleted file mode 100644 index 5433993..0000000 --- a/ipmitool-1.8.13.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df2f7f44b6f72db87fb33e99a7df02ae2dec6cf915322b9bab0c0745bf8d5748 -size 426220 diff --git a/ipmitool-1.8.15.tar.bz2 b/ipmitool-1.8.15.tar.bz2 new file mode 100644 index 0000000..952adcb --- /dev/null +++ b/ipmitool-1.8.15.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4acd2df5f8740fef5c032cebee0113ec4d3bbef04a6f4dbfaf7fcc7f3eb08c40 +size 747174 diff --git a/ipmitool-1_8_15_HEAD.patch b/ipmitool-1_8_15_HEAD.patch new file mode 100644 index 0000000..de040e6 --- /dev/null +++ b/ipmitool-1_8_15_HEAD.patch @@ -0,0 +1,14169 @@ +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