diff --git a/fix_dell_oem_exitcode b/fix_dell_oem_exitcode deleted file mode 100644 index 391dc93..0000000 --- a/fix_dell_oem_exitcode +++ /dev/null @@ -1,38 +0,0 @@ -From: Paul Zirnik -Return proper error value for Dell oem commands - easy and obvious fix - -Signed-off-by: Thomas Renninger - -diff --git a/lib/ipmi_delloem.c b/lib/ipmi_delloem.c -index d18e84a..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; diff --git a/ipmitool-1_8_15_HEAD.patch b/ipmitool-1_8_15_HEAD.patch index 4701c34..de040e6 100644 --- a/ipmitool-1_8_15_HEAD.patch +++ b/ipmitool-1_8_15_HEAD.patch @@ -1,14 +1,5 @@ -These is the git diff of version IPMITOOL_1_8_15 up to latest HEAD. -Last patch is: -commit 708be8bc450f907cddb6d9e4b83aee6ba67b7d04 -Author: Zdenek Styblik -Date: Fri Jan 9 12:48:35 2015 +0100 -Repo: git://git.code.sf.net/p/ipmitool/source - -Signed-off-by: Thomas Renninger - diff --git a/configure.ac b/configure.ac -index 6c5ccfb..d7c5620 100644 +index 6c5ccfb..c1d0992 100644 --- a/configure.ac +++ b/configure.ac @@ -26,14 +26,13 @@ AC_C_CONST @@ -27,6 +18,509 @@ index 6c5ccfb..d7c5620 100644 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 @@ -44,14 +538,157 @@ index b6ee7fa..b7ad628 100644 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..a59065b 100644 +index 7cbb9ad..89e4738 100644 --- a/include/ipmitool/ipmi_channel.h +++ b/include/ipmitool/ipmi_channel.h -@@ -181,74 +181,6 @@ struct get_channel_access_rsp { +@@ -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 @@ -119,10 +756,338 @@ index 7cbb9ad..a59065b 100644 -#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); - int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv); +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 @@ -201,17 +1166,17 @@ index cacdb2d..53a8c1f 100644 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..b298bb3 100644 +index 4a8e481..fd727ca 100644 --- a/include/ipmitool/ipmi_user.h +++ b/include/ipmitool/ipmi_user.h -@@ -38,58 +38,38 @@ +@@ -38,58 +38,46 @@ #endif #include -+#define IPMI_USER_ENABLE_UNSPECIFIED 0x00 -+#define IPMI_USER_ENABLE_ENABLED 0x40 -+#define IPMI_USER_ENABLE_DISABLED 0x80 -+#define IPMI_USER_ENABLE_RESERVED 0xC0 ++#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 @@ -261,7 +1226,11 @@ index 4a8e481..b298bb3 100644 -#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; @@ -290,8 +1259,79 @@ index 4a8e481..b298bb3 100644 +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 @@ -349,7 +1389,7 @@ index 91ae117..912b211 100644 msg_data[1] = offset & 0xFF; msg_data[2] = offset >> 8; diff --git a/lib/helper.c b/lib/helper.c -index 95d641e..30546f7 100644 +index 95d641e..b9316c4 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -29,6 +29,7 @@ @@ -360,7 +1400,7 @@ index 95d641e..30546f7 100644 #include #include -@@ -671,6 +672,37 @@ ipmi_start_daemon(struct ipmi_intf *intf) +@@ -671,6 +672,43 @@ ipmi_start_daemon(struct ipmi_intf *intf) dup(fd); } @@ -384,6 +1424,12 @@ index 95d641e..30546f7 100644 + 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; + } @@ -398,7 +1444,7 @@ index 95d641e..30546f7 100644 /* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed * on error. * FRU ID range: <0..255> -@@ -700,9 +732,9 @@ is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr) +@@ -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. * @@ -411,7 +1457,7 @@ index 95d641e..30546f7 100644 * * @argv_ptr: source string to convert from; usually argv * @channel_ptr: pointer where to store result -@@ -719,14 +751,14 @@ is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr) +@@ -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) @@ -428,7 +1474,7 @@ index 95d641e..30546f7 100644 return (-1); } -@@ -760,6 +792,36 @@ is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr) +@@ -760,6 +798,36 @@ is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr) return (-1); } @@ -481,10 +1527,10 @@ index 6cb2f80..6420629 100644 } diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c -index 43db338..8a52f9e 100644 +index 43db338..95017b8 100644 --- a/lib/ipmi_channel.c +++ b/lib/ipmi_channel.c -@@ -50,6 +50,7 @@ +@@ -50,11 +50,176 @@ #include #include #include @@ -492,7 +1538,177 @@ index 43db338..8a52f9e 100644 extern int csv_output; extern int verbose; -@@ -68,8 +69,7 @@ ipmi_1_5_authtypes(uint8_t n) + +-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]; @@ -502,7 +1718,20 @@ index 43db338..8a52f9e 100644 for (i = 0; ipmi_authtype_vals[i].val != 0; i++) { if (n & ipmi_authtype_vals[i].val) { strcat(supportedTypes, ipmi_authtype_vals[i].str); -@@ -89,27 +89,26 @@ ipmi_1_5_authtypes(uint8_t n) +@@ -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 @@ -538,7 +1767,7 @@ index 43db338..8a52f9e 100644 /* * It's very possible that this failed because we asked for IPMI v2 data * Ask again, without requesting IPMI v2 data -@@ -119,12 +118,12 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, +@@ -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"); @@ -553,7 +1782,7 @@ index 43db338..8a52f9e 100644 } } -@@ -135,9 +134,10 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, +@@ -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)); @@ -565,49 +1794,382 @@ index 43db338..8a52f9e 100644 printf("Per message authentication : %sabled\n", (auth_cap.per_message_auth) ? "dis" : "en"); -@@ -184,18 +184,18 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf, - * - */ - int +@@ -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) -+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; +- uint8_t rqdata[2]; +- uint8_t medium; - struct get_channel_info_rsp channel_info; -+ struct get_channel_info_rsp channel_info; - struct get_channel_access_rsp channel_access; +- 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_INFO; - req.msg.data = &channel; - req.msg.data_len = 1; ++ 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; -@@ -257,10 +257,9 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) - rqdata[0] = channel & 0xf; + 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; + } - /* get volatile settings */ +- 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; + } - - rqdata[1] = 0x80; /* 0x80=active */ + 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.netfn = IPMI_NETFN_APP; -+ req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; - req.msg.data = rqdata; - req.msg.data_len = 2; +- 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); + } -@@ -352,61 +351,35 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) +- 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 +-static int -ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) -+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; @@ -645,6 +2207,49 @@ index 43db338..8a52f9e 100644 - 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; @@ -652,7 +2257,7 @@ index 43db338..8a52f9e 100644 + int init = 1; + int max_uid = 0; + -+ curr_uid = userid ? userid : 1; ++ curr_uid = user_id ? user_id : 1; + do { + memset(&user_access, 0, sizeof(user_access)); + user_access.channel = channel; @@ -665,31 +2270,20 @@ index 43db338..8a52f9e 100644 + return (-1); } -- memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); -- -- rqdata[0] = curr_uid & 0x3f; -- -- 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; + memset(&user_name, 0, sizeof(user_name)); + user_name.user_id = curr_uid; + ccode = _ipmi_get_user_name(intf, &user_name); -+ if (eval_ccode(ccode) != 0) { ++ 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 +389,7 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) +@@ -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); @@ -698,19 +2292,27 @@ index 43db338..8a52f9e 100644 printf("Fixed Name : %s\n", (curr_uid <= user_access.fixed_user_ids) ? "Yes" : "No"); printf("Access Available : %s\n", -@@ -429,162 +402,56 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) +@@ -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 (!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; @@ -720,18 +2322,30 @@ index 43db338..8a52f9e 100644 - int i; - - if ((argc < 3) || (strncmp(argv[0], "help", 4) == 0)) { -- printf_channel_usage(); -- return 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]); -- return (-1); -- } ++ } 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]); -- return (-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; @@ -753,7 +2367,15 @@ index 43db338..8a52f9e 100644 - 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)); - @@ -769,7 +2391,8 @@ index 43db338..8a52f9e 100644 - - for (i = 2; i < argc; i ++) - { -- if (strncmp(argv[i], "callin=", 7) == 0) { ++ 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) { @@ -782,7 +2405,11 @@ index 43db338..8a52f9e 100644 - 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 { @@ -814,85 +2441,67 @@ index 43db338..8a52f9e 100644 -} - - - static const char * - iana_string(uint32_t iana) - { - static char s[10]; - +-static const char * +-iana_string(uint32_t iana) +-{ +- static char s[10]; +- - if (iana) - { -+ if (iana) { - sprintf(s, "%06x", iana); - return s; +- sprintf(s, "%06x", iana); +- return s; - } - else -+ } else { - return "N/A"; -+ } - } - - - static int +- return "N/A"; +-} +- +- +-static int -ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, - const char * payload_type, - uint8_t channel) -+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; - +- struct ipmi_rq req; +- - uint8_t oem_record; - uint8_t rqdata[3]; -+ uint8_t oem_record; -+ uint8_t rqdata[3]; - uint32_t iana; +- 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 -+ 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; +- uint16_t offset = 0; - uint16_t cipher_suite_data_length = 0; // how much was returned, total -+ /* 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)); +- +- 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.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); +- 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 -+ /* Always ask for cipher suite format */ -+ rqdata[2] = 0x80; - - rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { -@@ -598,23 +465,26 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, - } - - +- +- 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) -+ /* -+ * Grab the returned channel number once. We assume it's the same -+ * in future calls. -+ */ -+ if (rsp->data_len >= 1) { - channel = rsp->data[0]; +- channel = rsp->data[0]; - - while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) - { @@ -900,56 +2509,46 @@ index 43db338..8a52f9e 100644 - // 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"); -+ } -+ -+ 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; - +- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); +- offset += rsp->data_len - 1; +- - // - // Increment our list for the next call - // -+ /* -+ * Increment our list for the next call -+ */ - ++list_index; - rqdata[2] = (rqdata[2] & 0x80) + list_index; - -@@ -631,78 +501,68 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, - } - - /* Copy last chunk */ +- ++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"); -+ 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; - } - +- 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. - // -+ /* We can chomp on all our data now. */ - cipher_suite_data_length = offset; - offset = 0; - +- cipher_suite_data_length = offset; +- offset = 0; +- - if (! csv_output) -+ if (! csv_output) { - printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n"); +- printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n"); - - while (offset < cipher_suite_data_length) - { @@ -957,23 +2556,20 @@ index 43db338..8a52f9e 100644 - { - oem_record = 0; // standard type - iana = 0; -+ } -+ while (offset < cipher_suite_data_length) { -+ if (cipher_suite_data[offset++] == 0xC0) { -+ /* standard type */ -+ oem_record = 0; -+ iana = 0; - +- - // Verify that we have at least a full record left - if ((cipher_suite_data_length - offset) < 4) // id + 3 algs - { -+ /* 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; +- 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++]; +- cipher_suite_id = cipher_suite_data[offset++]; - - } - else if (cipher_suite_data[offset++] == 0xC1) @@ -983,37 +2579,32 @@ index 43db338..8a52f9e 100644 - // Verify that we have at least a full record left - if ((cipher_suite_data_length - offset) < 4) // id + iana + 3 algs - { -+ } else if (cipher_suite_data[offset++] == 0xC1) { -+ /* OEM record type */ -+ oem_record = 1; -+ -+ /* 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; +- 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++]; - +- +- cipher_suite_id = cipher_suite_data[offset++]; +- - // - // Grab the IANA - // -+ /* Grab the IANA */ - iana = - cipher_suite_data[offset] | - (cipher_suite_data[offset + 1] << 8) | - (cipher_suite_data[offset + 2] << 16); - offset += 3; +- iana = +- cipher_suite_data[offset] | +- (cipher_suite_data[offset + 1] << 8) | +- (cipher_suite_data[offset + 2] << 16); +- offset += 3; - } - else - { -+ } else { - lprintf(LOG_ERR, "Bad start of record byte in cipher suite data"); - return -1; - } - +- 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 @@ -1022,90 +2613,108 @@ index 43db338..8a52f9e 100644 - // allowing one algorithm per type (auth, integrity, crypt) because I - // don't I understand how it could be otherwise. - // -+ /* -+ * 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; -@@ -713,24 +573,20 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, - switch (cipher_suite_data[offset] & 0xC0) - { - case 0x00: +- 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 -+ /* Authentication algorithm specifier */ - auth_alg = cipher_suite_data[offset++] & 0x3F; - break; - case 0x40: +- auth_alg = cipher_suite_data[offset++] & 0x3F; +- break; +- case 0x40: - // Interity algorithm specifier -+ /* Interity algorithm specifier */ - integrity_alg = cipher_suite_data[offset++] & 0x3F; - break; - case 0x80: +- integrity_alg = cipher_suite_data[offset++] & 0x3F; +- break; +- case 0x80: - // Confidentiality algorithm specifier -+ /* Confidentiality algorithm specifier */ - crypt_alg = cipher_suite_data[offset++] & 0x3F; - break; +- 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 - // -+ /* 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, -@@ -739,17 +595,15 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, - val2str(integrity_alg, ipmi_integrity_algorithms), - val2str(crypt_alg, ipmi_encryption_algorithms)); +- 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 +- return 0; +-} +- +- +- +-uint8_t -ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel) -+ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel) - { +-{ - struct ipmi_rs * rsp; -+ struct ipmi_rs *rsp; - struct ipmi_rq req; - struct get_channel_info_rsp info; - -@@ -765,8 +619,9 @@ ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel) - return 0; - } - if (rsp->ccode > 0) { +- 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) -+ 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; -@@ -781,7 +636,7 @@ ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel) - } - - uint8_t +- 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) -+ipmi_current_channel_medium(struct ipmi_intf *intf) - { - return ipmi_get_channel_medium(intf, 0xE); - } -@@ -789,115 +644,182 @@ ipmi_current_channel_medium(struct ipmi_intf * intf) - void - printf_channel_usage() - { +-{ +- 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 " @@ -1119,154 +2728,52 @@ index 43db338..8a52f9e 100644 - lprintf(LOG_NOTICE, " 4 Administrator level"); - lprintf(LOG_NOTICE, " 5 OEM Proprietary level"); - lprintf(LOG_NOTICE, " 15 No access"); -+ 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"); ++ 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_set_user_access(struct ipmi_intf *intf, int argc, char **argv) ++ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) { -- int retval = 0; + int retval = 0; - uint8_t channel, priv = 0; - - if ((argc == 0) || (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; -+ } else if (argc < 3) { -+ lprintf(LOG_ERR, "Not enough parameters given."); -+ printf_channel_usage(); -+ return (-1); - } -- 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 (is_ipmi_channel_num(argv[0], &channel) != 0 -+ || is_ipmi_user_id(argv[1], &user_id) != 0) { -+ 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); -+ } -+ for (i = 3; i < argc; i ++) { -+ if (strncmp(argv[i], "callin=", 7) == 0) { -+ if (strncmp(argv[i] + 7, "off", 3) == 0) { -+ user_access.callin_callback = 1; -+ } else { -+ user_access.callin_callback = 0; -+ } -+ } 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; - } -- if (str2uchar(argv[2], &priv) != 0) { -- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); -+ } 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; -+ } -+ } 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); - } -- retval = ipmi_get_channel_auth_cap(intf, channel, priv); -+ user_access.privilege_limit = priv; -+ } else { -+ lprintf(LOG_ERR, "Invalid option: %s\n", argv[i]); -+ return (-1); - } - } -- else if (strncmp(argv[0], "getaccess", 10) == 0) -- { -- if ((argc < 2) || (argc > 3)) -+ 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); -+ } -+ 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) -+{ -+ int retval = 0; + uint8_t channel; + uint8_t priv = 0; + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); -+ printf_channel_usage(); + 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) { + if (argc != 3) { printf_channel_usage(); -- else { -- uint8_t ch = 0; -- uint8_t id = 0; -- if (str2uchar(argv[1], &ch) != 0) { + return (-1); +- } else { +- if (str2uchar(argv[1], &channel) != 0) { - lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); -+ return (-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); @@ -1276,7 +2783,12 @@ index 43db338..8a52f9e 100644 + uint8_t user_id = 0; + if ((argc < 2) || (argc > 3)) { + lprintf(LOG_ERR, "Not enough parameters given."); -+ printf_channel_usage(); + 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) { @@ -1359,21 +2871,2703 @@ index 43db338..8a52f9e 100644 - } - else - { +- printf("Invalid CHANNEL command: %s\n", argv[0]); + retval = ipmi_get_channel_cipher_suites(intf, + argv[1], /* ipmi | sol */ + channel); + } else { - printf("Invalid CHANNEL command: %s\n", argv[0]); ++ 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..3cfed96 100644 +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(); @@ -1433,11 +5627,59 @@ index 308c513..3cfed96 100644 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..8c6d12d 100644 +index 96d3b44..afee48b 100644 --- a/lib/ipmi_ekanalyzer.c +++ b/lib/ipmi_ekanalyzer.c -@@ -2773,6 +2773,10 @@ ipmi_ek_display_board_info_area(FILE *input_file, char *board_type, +@@ -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!"); @@ -1449,11 +5691,52 @@ index 96d3b44..8c6d12d 100644 } printf("Additional Custom Mfg. Data: %02x", diff --git a/lib/ipmi_firewall.c b/lib/ipmi_firewall.c -index 8bda398..2803bc0 100644 +index 8bda398..c3f51ad 100644 --- a/lib/ipmi_firewall.c +++ b/lib/ipmi_firewall.c -@@ -1110,7 +1110,11 @@ ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) - unsigned int l, n, c, ret; +@@ -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)) { @@ -1465,8 +5748,74 @@ index 8bda398..2803bc0 100644 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..066d929 100644 +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, @@ -1492,8 +5841,101 @@ index 68f40d4..066d929 100644 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..6a24831 100644 +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) @@ -1505,11 +5947,641 @@ index 48dc684..6a24831 100644 } 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..11e0d9c 100644 +index 060e753..bb619eb 100644 --- a/lib/ipmi_lanp.c +++ b/lib/ipmi_lanp.c -@@ -1198,8 +1198,7 @@ get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf) +@@ -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. */ @@ -1519,8 +6591,908 @@ index 060e753..11e0d9c 100644 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..26f3457 100644 +index 2bbbe4b..cfb05f7 100644 --- a/lib/ipmi_main.c +++ b/lib/ipmi_main.c @@ -1,21 +1,21 @@ @@ -1558,7 +7530,7 @@ index 2bbbe4b..26f3457 100644 #include #include -@@ -263,13 +264,18 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ +@@ -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. @@ -1571,13 +7543,130 @@ index 2bbbe4b..26f3457 100644 if (ipmi_main_intf != NULL) { printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc); + /* reduce retry count to a single retry */ -+ if (ipmi_main_intf->session) { -+ ipmi_main_intf->session->retry = 1; -+ } ++ 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 @@ -1744,7 +7833,7 @@ index 154bf40..1beebf0 100644 ptbl = NULL; } diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c -index 7a66aa5..914d11d 100644 +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) @@ -1766,11 +7855,149 @@ index 7a66aa5..914d11d 100644 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..a445a6e 100644 +index f3bc271..f5bf78a 100644 --- a/lib/ipmi_sdradd.c +++ b/lib/ipmi_sdradd.c -@@ -633,6 +633,7 @@ ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue) +@@ -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; } @@ -1779,10 +8006,55 @@ index f3bc271..a445a6e 100644 } diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c -index 67e12e3..81d007e 100644 +index 67e12e3..5df66a7 100644 --- a/lib/ipmi_sel.c +++ b/lib/ipmi_sel.c -@@ -536,7 +536,6 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) +@@ -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; @@ -1790,7 +8062,22 @@ index 67e12e3..81d007e 100644 int sensor_type; uint8_t i = 0; uint16_t oem_id = 0; -@@ -587,17 +586,19 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) +@@ -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) { @@ -1814,7 +8101,35 @@ index 67e12e3..81d007e 100644 if (oem_id == supermicro_x9[i]) { chipset_type = 2; break; -@@ -1234,6 +1235,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char +@@ -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 */ @@ -1823,7 +8138,7 @@ index 67e12e3..81d007e 100644 } if( evt == NULL ){ lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", -@@ -1247,6 +1250,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char +@@ -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; @@ -1832,7 +8147,7 @@ index 67e12e3..81d007e 100644 } } if( evt == NULL ){ -@@ -1915,6 +1920,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) +@@ -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; @@ -1841,7 +8156,75 @@ index 67e12e3..81d007e 100644 } /* * Sensor-Specific Discrete -@@ -2919,7 +2926,7 @@ ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv) +@@ -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..d77ed01 100644 +index c138c67..063dfb0 100644 --- a/lib/ipmi_sensor.c +++ b/lib/ipmi_sensor.c @@ -1,21 +1,21 @@ @@ -1905,7 +8299,15 @@ index c138c67..d77ed01 100644 * Note: rsp->data[0] would point to the next valid entry in the sampling table */ // BUGBUG: uses 'hardcoded' length information from SDR Definition -@@ -892,8 +892,20 @@ ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv) +@@ -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; @@ -1929,9 +8331,43 @@ index c138c67..d77ed01 100644 verbose = v; sdr = NULL; diff --git a/lib/ipmi_sol.c b/lib/ipmi_sol.c -index cf58b44..244a27e 100644 +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; @@ -1941,6 +8377,89 @@ index cf58b44..244a27e 100644 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; @@ -1952,6 +8471,111 @@ index cf58b44..244a27e 100644 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 @@ -1967,7 +8591,7 @@ index 16a6090..7f7a58b 100644 } diff --git a/lib/ipmi_tsol.c b/lib/ipmi_tsol.c -index b4e3cc1..d7460bd 100644 +index b4e3cc1..70d7357 100644 --- a/lib/ipmi_tsol.c +++ b/lib/ipmi_tsol.c @@ -29,6 +29,7 @@ @@ -1978,6 +8602,71 @@ index b4e3cc1..d7460bd 100644 #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; @@ -1990,7 +8679,29 @@ index b4e3cc1..d7460bd 100644 } } -@@ -440,7 +443,7 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv) +@@ -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; @@ -1999,14 +8710,28 @@ index b4e3cc1..d7460bd 100644 } 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..31a5ca5 100644 +index d7e5890..6074209 100644 --- a/lib/ipmi_user.c +++ b/lib/ipmi_user.c -@@ -58,244 +58,245 @@ extern int csv_output; - #define IPMI_PASSWORD_SET_PASSWORD 0x02 - #define IPMI_PASSWORD_TEST_PASSWORD 0x03 +@@ -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 @@ -2099,7 +8824,7 @@ index d7e5890..31a5ca5 100644 -/* - * ipmi_get_user_name +/* _ipmi_get_user_name - Fetch User Name for given User ID. User Name is stored -+ * into passed structure. ++ * into passed structure. * - * param intf [in] - * param channel_number [in] @@ -2160,7 +8885,7 @@ index d7e5890..31a5ca5 100644 + return (-1); + } else if (rsp->ccode > 0) { + return rsp->ccode; -+ } else if (rsp->data_len != 17) { ++ } else if (rsp->data_len != 16) { + return (-2); } - @@ -2172,8 +8897,6 @@ index d7e5890..31a5ca5 100644 + return rsp->ccode; } -- -- +/* _ipmi_set_user_access - Set User Access for given channel. + * + * @intf - IPMI interface @@ -2214,9 +8937,59 @@ index d7e5890..31a5ca5 100644 + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); -+ } else { ++ } 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 @@ -2341,20 +9114,18 @@ index d7e5890..31a5ca5 100644 + memset(&user_name, 0, sizeof(user_name)); + user_name.user_id = current_user_id; + ccode = _ipmi_get_user_name(intf, &user_name); -+ if (eval_ccode(ccode) != 0) { ++ 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 ((current_user_id == 0) -+ || user_access.link_auth -+ || user_access.ipmi_messaging -+ || strcmp("", (char *)user_name.user_name)) { -+ 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); -+ } ++ 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); } - - @@ -2435,7 +9206,7 @@ index d7e5890..31a5ca5 100644 /* * ipmi_user_set_username */ -@@ -343,47 +344,6 @@ ipmi_user_set_username( +@@ -343,125 +387,17 @@ ipmi_user_set_username( return 0; } @@ -2480,19 +9251,96 @@ index d7e5890..31a5ca5 100644 - return 0; -} - - /* - * ipmi_user_set_password - * -@@ -441,8 +401,6 @@ ipmi_user_set_password( - 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); -- -- - /* - * ipmi_user_test_password - * -@@ -487,16 +445,40 @@ ipmi_user_test_password( + switch (ret) { + case 0: +@@ -487,16 +423,40 @@ ipmi_user_test_password( static void print_user_usage(void) { @@ -2542,7 +9390,7 @@ index d7e5890..31a5ca5 100644 } -@@ -509,328 +491,276 @@ ipmi_user_build_password_prompt(uint8_t user_id) +@@ -509,328 +469,282 @@ ipmi_user_build_password_prompt(uint8_t user_id) return prompt; } @@ -2553,13 +9401,12 @@ index d7e5890..31a5ca5 100644 * - * 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) + * @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) { @@ -2659,9 +9506,6 @@ index d7e5890..31a5ca5 100644 - { - print_user_usage(); - return -1; -- } -- -- retval = ipmi_print_user_list(intf, channel); +int +ipmi_user_test(struct ipmi_intf *intf, int argc, char **argv) +{ @@ -2673,9 +9517,42 @@ index d7e5890..31a5ca5 100644 + 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 @@ -2739,31 +9616,32 @@ index d7e5890..31a5ca5 100644 - { - print_user_usage(); - return -1; -+ if (is_ipmi_user_id(argv[1], &user_id)) { ++ if (argc != 3 && argc != 4) { ++ print_user_usage(); + 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"); ++ if (argc == 4) { ++ if (is_ipmi_channel_num(argv[3], &user_access.channel) != 0) { + return (-1); } + } else { -+ password = argv[3]; ++ /* Use channel running on */ ++ user_access.channel = 0x0E; } -+ return ipmi_user_test_password(intf, -+ user_id, -+ password, -+ password_length == 20); ++ 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; ++ } +} - /* @@ -2833,10 +9711,11 @@ index d7e5890..31a5ca5 100644 - return -1; - } +int -+ipmi_user_priv(struct ipmi_intf *intf, int argc, char **argv) ++ipmi_user_mod(struct ipmi_intf *intf, int argc, char **argv) +{ -+ struct user_access_t user_access; -+ int ccode = 0; ++ /* Disable / Enable */ ++ uint8_t user_id; ++ uint8_t operation; - retval = ipmi_user_set_password(intf, - user_id, @@ -2847,33 +9726,16 @@ index d7e5890..31a5ca5 100644 - free(password); - password = NULL; - } -+ if (argc != 3 && argc != 4) { +- } ++ if (argc != 2) { + 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) { ++ if (is_ipmi_user_id(argv[1], &user_id)) { + 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; -+ } -+} ++ operation = (strncmp(argv[0], "disable", 7) == 0) ? ++ IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER; - /* - * Set Name @@ -2890,70 +9752,27 @@ index d7e5890..31a5ca5 100644 - 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_mod(struct ipmi_intf *intf, int argc, char **argv) -+{ -+ /* Disable / Enable */ -+ uint8_t user_id; -+ uint8_t operation; -+ char null_password[16]; /* Not used, but required */ - -- retval = ipmi_user_set_username(intf, user_id, argv[3]); -- } -- else -- { -- print_user_usage(); -- return -1; -- } -+ if (argc != 2) { -+ print_user_usage(); -+ return (-1); -+ } -+ if (is_ipmi_user_id(argv[1], &user_id)) { -+ return (-1); - } -+ memset(null_password, 0, sizeof(null_password)); -+ operation = (strncmp(argv[0], "disable", 7) == 0) ? -+ IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER; - -- else if (strncmp(argv[0], "priv", 4) == 0) -- { -- uint8_t user_id; -- uint8_t priv_level; -- uint8_t channel = 0x0e; /* Use channel running on */ -+ /* Last parameter is ignored */ -+ return ipmi_user_set_password(intf, user_id, operation, null_password, 0); -+} - -- if (argc != 3 && argc != 4) -- { -- print_user_usage(); -- 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); + } -- if (argc == 4) -- { -- if (str2uchar(argv[3], &channel) != 0) -- { -- lprintf(LOG_ERR, "Invalid channel: %s", argv[3]); -- return (-1); -- } -- channel = (channel & 0x0f); +- retval = ipmi_user_set_username(intf, user_id, argv[3]); + if (argc == 3) { + /* We need to prompt for a password */ + char *tmp; @@ -2962,44 +9781,84 @@ index d7e5890..31a5ca5 100644 + lprintf(LOG_ERR, "ipmitool: malloc failure"); + return (-1); } -- -- if (str2uchar(argv[2], &priv_level) != 0) +- else - { -- lprintf(LOG_ERR, "Invalid privilege level: %s", argv[2]); +- print_user_usage(); +- return -1; + tmp = ask_password(user_id); + if (tmp == NULL) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); - return (-1); ++ return (-1); } -- priv_level = (priv_level & 0x0f); +- } - -- if (is_ipmi_user_id(argv[1], &user_id)) { +- 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); ++ 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); -+ } + 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); + } -- retval = ipmi_user_set_userpriv(intf,channel,user_id,priv_level); +- 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 @@ -3010,14 +9869,6 @@ index d7e5890..31a5ca5 100644 - uint8_t user_id; - uint8_t operation; - char null_password[16]; /* Not used, but required */ -+ return ipmi_user_set_password(intf, -+ user_id, -+ IPMI_PASSWORD_SET_PASSWORD, -+ password, -+ password_type > 16); -+} - -- memset(null_password, 0, sizeof(null_password)); +int +ipmi_user_name(struct ipmi_intf *intf, int argc, char **argv) +{ @@ -3035,15 +9886,12 @@ index d7e5890..31a5ca5 100644 + return (-1); + } -- if (argc != 2) -- { -- print_user_usage(); -- return -1; -- } +- memset(null_password, 0, sizeof(null_password)); + return ipmi_user_set_username(intf, user_id, argv[3]); +} -- if (is_ipmi_user_id(argv[1], &user_id)) { +- if (argc != 2) +- { +/* + * ipmi_user_main + * @@ -3077,7 +9925,11 @@ index d7e5890..31a5ca5 100644 + && (strncmp("name", argv[1], 4) == 0)) { + return ipmi_user_name(intf, argc, argv); + } else { -+ print_user_usage(); + print_user_usage(); +- return -1; +- } +- +- if (is_ipmi_user_id(argv[1], &user_id)) { return (-1); } - @@ -3106,8 +9958,1026 @@ index d7e5890..31a5ca5 100644 - - 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