forked from pool/ipmitool
Thomas Renninger
ee43dfb67f
- Update to latest ipmitool source code commit 999cd0ad9192b19ec57574e7aca111571f4d21d8 Date: Fri Mar 6 09:03:05 2015 -0600 and throw away patches that went mainline. OBS-URL: https://build.opensuse.org/request/show/339080 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement/ipmitool?expand=0&rev=31
14170 lines
410 KiB
Diff
14170 lines
410 KiB
Diff
diff --git a/configure.ac b/configure.ac
|
|
index 6c5ccfb..c1d0992 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -26,14 +26,13 @@ AC_C_CONST
|
|
AC_C_INLINE
|
|
AC_C_BIGENDIAN
|
|
|
|
-AC_FUNC_MALLOC
|
|
AC_FUNC_SELECT_ARGTYPES
|
|
AC_FUNC_STRTOD
|
|
AC_CHECK_FUNCS([alarm gethostbyname getaddrinfo getifaddrs socket select])
|
|
AC_CHECK_FUNCS([memmove memset strchr strdup strerror])
|
|
AC_CHECK_FUNCS([getpassphrase])
|
|
|
|
-CFLAGS="$CFLAGS -fno-strict-aliasing -Wreturn-type"
|
|
+CFLAGS="$CFLAGS -Wall -Wextra -std=c99 -pedantic -Wformat -Wformat-nonliteral"
|
|
|
|
AM_PROG_LIBTOOL
|
|
LIBTOOL="$LIBTOOL --silent"
|
|
@@ -60,6 +59,7 @@ dnl
|
|
xenable_intf_bmc=no
|
|
xenable_intf_imb=yes
|
|
xenable_intf_open=yes
|
|
+xenable_intf_usb=yes
|
|
xenable_intf_lipmi=yes
|
|
#xenable_intf_serial=yes
|
|
xenable_intf_dummy=no
|
|
@@ -131,6 +131,24 @@ if test "x$xenable_all_options" = "xyes" || test "x$xenable_solaris_opt" = "xyes
|
|
AC_DEFINE(ENABLE_ALL_OPTIONS, [1], [Define to 1 to enable all command line options.])
|
|
fi
|
|
|
|
+dnl Determine anonymous union/structure support in GCC
|
|
+AC_TRY_COMPILE([
|
|
+#include <stdio.h>
|
|
+ ], [
|
|
+ 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 <charles_rose@dell.com>
|
|
+# Jordan Hargrave <jordan_hargrave@dell.com>
|
|
+#
|
|
+# 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 <os_boot|os_shutdown|inst_start|inst_complete|inst_abort|inst_fail>" ;;
|
|
+ 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 <platform|CPU|Memory>
|
|
+.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 <watts> \fIpolicy_id\fP <0-7> [\fIcorrection\fP auto|soft|hard] \fItrig_lim\fP <seconds> \fIstats\fP <seconds> [\fIdomain\fP <platform|CPU|Memory>] \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 <temp> \fIpolicy_id\fP <0-7> [\fIcorrection\fP auto|soft|hard] \fItrig_lim\fP <seconds> \fIstats\fP <seconds> [\fIdomain\fP <platform|CPU|Memory>] \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 <platform|CPU|Memory>]
|
|
+.br
|
|
+
|
|
+Remove a policy. If domain is not supplied a default of platform is used.
|
|
+.RE
|
|
+.TP
|
|
+\fIpower\fP \fImin\fP <minimum> \fImax\fP <maximum> [\fIdomain\fP <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>] <start> <stop> <repeat>
|
|
+.br
|
|
+
|
|
+Set Node Manager policy suspend periods.
|
|
+If domain is not supplied a default of platform is used.
|
|
+The <start> and <stop> values must be in the range of 0-239, which is the number of minutes past midnight divided by 6.
|
|
+The <repeat> 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 <platform|CPU|Memory>]
|
|
+.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 <platform|CPU|Memory>] \fIthresh_array\fP
|
|
+.br
|
|
+
|
|
+Set Node Manager policy Alert Threshold values.
|
|
+If domain is not supplied a default of platform is used.
|
|
+The \fIthresh_array\fP is 1, 2, or 3 integers that set three alert threshold settings. The setting type is a power or temperature value which must match the type of policy.
|
|
+
|
|
+.RE
|
|
+.RE
|
|
+
|
|
.TP
|
|
\fIpef\fP
|
|
.RS
|
|
diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am
|
|
index 925881e..5a9062c 100644
|
|
--- a/include/ipmitool/Makefile.am
|
|
+++ b/include/ipmitool/Makefile.am
|
|
@@ -38,5 +38,5 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
|
|
ipmi_oem.h ipmi_sdradd.h ipmi_isol.h ipmi_sunoem.h ipmi_picmg.h \
|
|
ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \
|
|
ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \
|
|
- ipmi_delloem.h ipmi_dcmi.h
|
|
+ ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h
|
|
|
|
diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h
|
|
index b6ee7fa..b7ad628 100644
|
|
--- a/include/ipmitool/helper.h
|
|
+++ b/include/ipmitool/helper.h
|
|
@@ -83,9 +83,12 @@ int str2ushort(const char * str, uint16_t * ushrt_ptr);
|
|
int str2char(const char * str, int8_t * chr_ptr);
|
|
int str2uchar(const char * str, uint8_t * uchr_ptr);
|
|
|
|
+int eval_ccode(const int ccode);
|
|
+
|
|
int is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr);
|
|
int is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr);
|
|
int is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr);
|
|
+int is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr);
|
|
|
|
uint16_t str2val(const char * str, const struct valstr * vs);
|
|
void print_valstr(const struct valstr * vs, const char * title, int loglevel);
|
|
diff --git a/include/ipmitool/ipmi.h b/include/ipmitool/ipmi.h
|
|
index 1fd3e2a..beda0ad 100644
|
|
--- a/include/ipmitool/ipmi.h
|
|
+++ b/include/ipmitool/ipmi.h
|
|
@@ -260,6 +260,7 @@ typedef enum IPMI_OEM {
|
|
IPMI_OEM_HITACHI_116 = 116,
|
|
IPMI_OEM_NEC = 119,
|
|
IPMI_OEM_TOSHIBA = 186,
|
|
+ IPMI_OEM_ERICSSON = 193,
|
|
IPMI_OEM_INTEL = 343,
|
|
IPMI_OEM_TATUNG = 373,
|
|
IPMI_OEM_HITACHI_399 = 399,
|
|
@@ -269,7 +270,9 @@ typedef enum IPMI_OEM {
|
|
IPMI_OEM_BROADCOM = 4413,
|
|
IPMI_OEM_MAGNUM = 5593,
|
|
IPMI_OEM_TYAN = 6653,
|
|
+ IPMI_OEM_QUANTA = 7244,
|
|
IPMI_OEM_NEWISYS = 9237,
|
|
+ IPMI_OEM_ADVANTECH = 10297,
|
|
IPMI_OEM_FUJITSU_SIEMENS = 10368,
|
|
IPMI_OEM_AVOCENT = 10418,
|
|
IPMI_OEM_PEPPERCON = 10437,
|
|
diff --git a/include/ipmitool/ipmi_channel.h b/include/ipmitool/ipmi_channel.h
|
|
index 7cbb9ad..89e4738 100644
|
|
--- a/include/ipmitool/ipmi_channel.h
|
|
+++ b/include/ipmitool/ipmi_channel.h
|
|
@@ -40,6 +40,7 @@
|
|
|
|
|
|
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
|
|
+#define IPMI_SET_CHANNEL_ACCESS 0x40
|
|
#define IPMI_GET_CHANNEL_ACCESS 0x41
|
|
#define IPMI_GET_CHANNEL_INFO 0x42
|
|
#define IPMI_SET_USER_ACCESS 0x43
|
|
@@ -49,6 +50,32 @@
|
|
#define IPMI_SET_USER_PASSWORD 0x47
|
|
#define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54
|
|
|
|
+/* These are for channel_info_t.session_support */
|
|
+#define IPMI_CHANNEL_SESSION_LESS 0x00
|
|
+#define IPMI_CHANNEL_SESSION_SINGLE 0x40
|
|
+#define IPMI_CHANNEL_SESSION_MULTI 0x80
|
|
+#define IPMI_CHANNEL_SESSION_BASED 0xC0
|
|
+
|
|
+/* (22.24) Get Channel Info */
|
|
+struct channel_info_t {
|
|
+ uint8_t channel;
|
|
+ uint8_t medium;
|
|
+ uint8_t protocol;
|
|
+ uint8_t session_support;
|
|
+ uint8_t active_sessions;
|
|
+ uint8_t vendor_id[3];
|
|
+ uint8_t aux_info[2];
|
|
+};
|
|
+
|
|
+/* (22.23) Get Channel Access */
|
|
+struct channel_access_t {
|
|
+ uint8_t access_mode;
|
|
+ uint8_t alerting;
|
|
+ uint8_t channel;
|
|
+ uint8_t per_message_auth;
|
|
+ uint8_t privilege_limit;
|
|
+ uint8_t user_level_auth;
|
|
+};
|
|
|
|
/*
|
|
* The Get Authentication Capabilities response structure
|
|
@@ -101,153 +128,12 @@ struct get_channel_auth_cap_rsp {
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
-
|
|
-
|
|
-/*
|
|
- * The Get Channel Info response structure
|
|
- * From table 22-29 of the IPMI v2.0 spec
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct get_channel_info_rsp {
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved1 : 4;
|
|
- uint8_t channel_number : 4; /* channel number */
|
|
-#else
|
|
- uint8_t channel_number : 4; /* channel number */
|
|
- uint8_t __reserved1 : 4;
|
|
-#endif
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved2 : 1;
|
|
- uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */
|
|
-#else
|
|
- uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */
|
|
- uint8_t __reserved2 : 1;
|
|
-#endif
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved3 : 3;
|
|
- uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */
|
|
-#else
|
|
- uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */
|
|
- uint8_t __reserved3 : 3;
|
|
-#endif
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t session_support : 2; /* Description of session support */
|
|
- uint8_t active_sessions : 6; /* Count of active sessions */
|
|
-#else
|
|
- uint8_t active_sessions : 6; /* Count of active sessions */
|
|
- uint8_t session_support : 2; /* Description of session support */
|
|
-#endif
|
|
- uint8_t vendor_id[3]; /* For OEM that specified the protocol */
|
|
- uint8_t aux_info[2]; /* Not used*/
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-
|
|
-/*
|
|
- * The Get Channel Access response structure
|
|
- * From table 22-28 of the IPMI v2.0 spec
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct get_channel_access_rsp {
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t alerting : 1;
|
|
- uint8_t per_message_auth : 1;
|
|
- uint8_t user_level_auth : 1;
|
|
- uint8_t access_mode : 3;
|
|
-#else
|
|
- uint8_t access_mode : 3;
|
|
- uint8_t user_level_auth : 1;
|
|
- uint8_t per_message_auth : 1;
|
|
- uint8_t alerting : 1;
|
|
- uint8_t __reserved1 : 2;
|
|
-#endif
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved2 : 4;
|
|
- uint8_t channel_priv_limit : 4; /* Channel privilege level limit */
|
|
-#else
|
|
- uint8_t channel_priv_limit : 4; /* Channel privilege level limit */
|
|
- uint8_t __reserved2 : 4;
|
|
-#endif
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct get_user_access_rsp {
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t max_user_ids : 6;
|
|
- uint8_t __reserved2 : 2;
|
|
- uint8_t enabled_user_ids : 6;
|
|
- uint8_t __reserved3 : 2;
|
|
- uint8_t fixed_user_ids : 6;
|
|
- uint8_t __reserved4 : 1;
|
|
- uint8_t callin_callback : 1;
|
|
- uint8_t link_auth : 1;
|
|
- uint8_t ipmi_messaging : 1;
|
|
- uint8_t privilege_limit : 4;
|
|
-#else
|
|
- uint8_t max_user_ids : 6;
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t enabled_user_ids : 6;
|
|
- uint8_t __reserved2 : 2;
|
|
- uint8_t fixed_user_ids : 6;
|
|
- uint8_t __reserved3 : 2;
|
|
- uint8_t privilege_limit : 4;
|
|
- uint8_t ipmi_messaging : 1;
|
|
- uint8_t link_auth : 1;
|
|
- uint8_t callin_callback : 1;
|
|
- uint8_t __reserved4 : 1;
|
|
-#endif
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct set_user_access_data {
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t change_bits : 1;
|
|
- uint8_t callin_callback : 1;
|
|
- uint8_t link_auth : 1;
|
|
- uint8_t ipmi_messaging : 1;
|
|
- uint8_t channel : 4;
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t user_id : 6;
|
|
- uint8_t __reserved2 : 4;
|
|
- uint8_t privilege_limit : 4;
|
|
- uint8_t __reserved3 : 4;
|
|
- uint8_t session_limit : 4;
|
|
-#else
|
|
- uint8_t channel : 4;
|
|
- uint8_t ipmi_messaging : 1;
|
|
- uint8_t link_auth : 1;
|
|
- uint8_t callin_callback : 1;
|
|
- uint8_t change_bits : 1;
|
|
- uint8_t user_id : 6;
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t privilege_limit : 4;
|
|
- uint8_t __reserved2 : 4;
|
|
- uint8_t session_limit : 4;
|
|
- uint8_t __reserved3 : 4;
|
|
-#endif
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
+int _ipmi_get_channel_access(struct ipmi_intf *intf,
|
|
+ struct channel_access_t *channel_access,
|
|
+ uint8_t get_volatile_settings);
|
|
+int _ipmi_set_channel_access(struct ipmi_intf *intf,
|
|
+ struct channel_access_t channel_access, uint8_t access_option,
|
|
+ uint8_t privilege_option);
|
|
|
|
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
|
|
uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf);
|
|
diff --git a/include/ipmitool/ipmi_dcmi.h b/include/ipmitool/ipmi_dcmi.h
|
|
index ce90857..15a959f 100644
|
|
--- a/include/ipmitool/ipmi_dcmi.h
|
|
+++ b/include/ipmitool/ipmi_dcmi.h
|
|
@@ -52,6 +52,53 @@
|
|
#define GOOD_PWR_GLIMIT_CCODE(ccode) ((ccode = ((ccode == 0x80) ? 0 : ccode)))
|
|
#define GOOD_ASSET_TAG_CCODE(ccode) ((ccode = (((ccode == 0x80) || (ccode == 0x81) || (ccode == 0x82) || (ccode == 0x83)) ? 0 : ccode)))
|
|
|
|
+/* External Node Manager Configuration and Control Commands per spec 2.0 */
|
|
+
|
|
+#define IPMI_NM_POLICY_CTL 0xC0
|
|
+#define IPMI_NM_SET_POLICY 0xC1
|
|
+#define IPMI_NM_GET_POLICY 0xC2
|
|
+#define IPMI_NM_SET_ALERT_TH 0xC3
|
|
+#define IPMI_NM_GET_ALERT_TH 0xC4
|
|
+#define IPMI_NM_SET_SUSPEND 0xC5
|
|
+#define IPMI_NM_GET_SUSPEND 0xC6
|
|
+#define IPMI_NM_RESET_STATS 0xC7
|
|
+#define IPMI_NM_GET_STATS 0xC8
|
|
+#define IPMI_NM_GET_CAP 0xC9
|
|
+#define IPMI_NM_GET_VERSION 0xCA
|
|
+#define IPMI_NM_SET_POWER 0xCB
|
|
+#define IPMI_NM_SET_ALERT_DS 0xCE
|
|
+#define IPMI_NM_GET_ALERT_DS 0xCF
|
|
+#define IPMI_NM_LIMITING 0xF2
|
|
+
|
|
+/* Node Manager Policy Control Flags */
|
|
+#define IPMI_NM_GLOBAL_ENABLE 0x01
|
|
+#define IPMI_NM_DOMAIN_ENABLE 0x02
|
|
+#define IPMI_NM_PER_POLICY_ENABLE 0x04
|
|
+
|
|
+/* Node Manager Set Policy Enable */
|
|
+#define IPMI_NM_POLICY_ENABLE 0x10
|
|
+
|
|
+/* Node Manager Policy Trigger Codes */
|
|
+#define IPMI_NM_NO_POLICY_TRIG 0x00
|
|
+#define IPMI_NM_TEMP_TRIGGER 0x01
|
|
+#define IPMI_NM_NO_READ_TRIG 0x02
|
|
+#define IPMI_NM_RESET_TRIGGER 0x03
|
|
+#define IPMI_NM_BOOT_TRIGGER 0x04
|
|
+
|
|
+/* Policy Exception Actions flags */
|
|
+#define IPMI_NM_POLICY_ALERT 0x01
|
|
+#define IPMI_NM_POLICY_SHUT 0x02
|
|
+
|
|
+/* Power Correction codes for Policy action */
|
|
+#define IPMI_NM_PWR_AUTO_CORR 0x00
|
|
+#define IPMI_NM_PWR_SOFT_CORR 0x01
|
|
+#define IPMI_NM_PWR_AGGR_CORR 0x02
|
|
+
|
|
+/* Set Threshold message size */
|
|
+#define IPMI_NM_SET_THRESH_LEN 12
|
|
+
|
|
+/* Number of Suspend Periods */
|
|
+#define IPMI_NM_SUSPEND_PERIOD_MAX 5
|
|
|
|
struct dcmi_cmd {
|
|
uint16_t val;
|
|
@@ -126,4 +173,98 @@ struct thermal_limit {
|
|
|
|
int ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char ** argv);
|
|
|
|
+/* Node Manager discover command */
|
|
+struct nm_discover {
|
|
+ uint8_t intel_id[3]; /* Always returns 000157 */
|
|
+ uint8_t nm_version;
|
|
+ uint8_t ipmi_version;
|
|
+ uint8_t patch_version;
|
|
+ uint8_t major_rev;
|
|
+ uint8_t minor_rev;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager get capabilites command */
|
|
+struct nm_capability {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t max_settings;
|
|
+ uint16_t max_value; /* max power/thermal/time after reset */
|
|
+ uint16_t min_value; /* min "" */
|
|
+ uint32_t min_corr; /* min correction time inmillesecs */
|
|
+ uint32_t max_corr;
|
|
+ uint16_t min_stats;
|
|
+ uint16_t max_stats;
|
|
+ uint8_t scope;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager get statistics command */
|
|
+struct nm_statistics {
|
|
+ uint8_t intel_id[3];
|
|
+ uint16_t curr_value;
|
|
+ uint16_t min_value;
|
|
+ uint16_t max_value;
|
|
+ uint16_t ave_value;
|
|
+ uint32_t time_stamp;
|
|
+ uint32_t stat_period;
|
|
+ uint8_t id_state;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager set policy */
|
|
+struct nm_policy {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
|
+ uint8_t policy_id;
|
|
+ uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
|
+ uint8_t policy_exception; /* exception actions */
|
|
+ uint16_t policy_limits;
|
|
+ uint32_t corr_time;
|
|
+ uint16_t trigger_limit;
|
|
+ uint16_t stats_period;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Maager get policy */
|
|
+struct nm_get_policy {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
|
+ uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
|
+ uint8_t policy_exception; /* exception actions */
|
|
+ uint16_t policy_limits;
|
|
+ uint32_t corr_time;
|
|
+ uint16_t trigger_limit;
|
|
+ uint16_t stats_period;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager set alert destination */
|
|
+struct nm_set_alert {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t chan; /* 0:3 BMC chan, 4:6 reserved, bit 7=0 register alert reciever =1 invalidate */
|
|
+ uint8_t dest; /* lan destination */
|
|
+ uint8_t string; /* alert string selector */
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager set alert threshold */
|
|
+struct nm_thresh {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
|
+ uint8_t policy_id;
|
|
+ uint8_t count;
|
|
+ uint16_t thresholds[3];
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager suspend period struct */
|
|
+struct nm_period {
|
|
+ uint8_t start;
|
|
+ uint8_t stop;
|
|
+ uint8_t repeat;
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+/* Node Manager set suspend period */
|
|
+struct nm_suspend {
|
|
+ uint8_t intel_id[3];
|
|
+ uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
|
+ uint8_t policy_id;
|
|
+ uint8_t count;
|
|
+ struct nm_period period[IPMI_NM_SUSPEND_PERIOD_MAX];
|
|
+} __attribute__ ((packed));
|
|
+
|
|
+int ipmi_nm_main(struct ipmi_intf * intf, int argc, char ** argv);
|
|
#endif /*IPMI_DCMI_H*/
|
|
diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h
|
|
index f9f6592..efec82d 100644
|
|
--- a/include/ipmitool/ipmi_intf.h
|
|
+++ b/include/ipmitool/ipmi_intf.h
|
|
@@ -62,36 +62,43 @@ enum LANPLUS_SESSION_STATE {
|
|
#define IPMI_SIK_BUFFER_SIZE 20
|
|
#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
|
|
|
|
-struct ipmi_session {
|
|
- char *hostname; /* Numeric IP adress or DNS name - see RFC 1034/RFC 1035 */
|
|
+struct ipmi_session_params {
|
|
+ char * hostname;
|
|
uint8_t username[17];
|
|
- uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1];
|
|
- uint8_t challenge[16];
|
|
- uint8_t authtype;
|
|
+ uint8_t authcode_set[IPMI_AUTHCODE_BUFFER_SIZE + 1];
|
|
uint8_t authtype_set;
|
|
-#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10
|
|
-#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08
|
|
-#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04
|
|
-#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02
|
|
-#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01
|
|
- uint8_t authstatus;
|
|
- uint8_t authextra;
|
|
uint8_t privlvl;
|
|
uint8_t cipher_suite_id;
|
|
char sol_escape_char;
|
|
int password;
|
|
int port;
|
|
- int active;
|
|
int retry;
|
|
+ uint32_t timeout;
|
|
+ uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
|
|
+ uint8_t lookupbit;
|
|
+};
|
|
|
|
+#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10
|
|
+#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08
|
|
+#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04
|
|
+#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02
|
|
+#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01
|
|
+
|
|
+struct ipmi_session {
|
|
+ int active;
|
|
uint32_t session_id;
|
|
uint32_t in_seq;
|
|
uint32_t out_seq;
|
|
+
|
|
+ uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1];
|
|
+ uint8_t challenge[16];
|
|
+ uint8_t authtype;
|
|
+ uint8_t authstatus;
|
|
+ uint8_t authextra;
|
|
uint32_t timeout;
|
|
|
|
struct sockaddr_storage addr;
|
|
socklen_t addrlen;
|
|
- int ai_family; /* Protocol family for socket. */
|
|
|
|
/*
|
|
* This struct holds state data specific to IPMI v2 / RMCP+ sessions
|
|
@@ -107,7 +114,6 @@ struct ipmi_session {
|
|
uint8_t integrity_alg;
|
|
uint8_t crypt_alg;
|
|
uint8_t max_priv_level;
|
|
- uint8_t lookupbit;
|
|
|
|
uint32_t console_id;
|
|
uint32_t bmc_id;
|
|
@@ -168,8 +174,10 @@ struct ipmi_intf {
|
|
int abort;
|
|
int noanswer;
|
|
int picmg_avail;
|
|
+ int vita_avail;
|
|
IPMI_OEM manufacturer_id;
|
|
|
|
+ struct ipmi_session_params ssn_params;
|
|
struct ipmi_session * session;
|
|
struct ipmi_oem_handle * oem;
|
|
struct ipmi_cmd * cmdlist;
|
|
diff --git a/include/ipmitool/ipmi_lanp.h b/include/ipmitool/ipmi_lanp.h
|
|
index 1aaae5e..ba25582 100644
|
|
--- a/include/ipmitool/ipmi_lanp.h
|
|
+++ b/include/ipmitool/ipmi_lanp.h
|
|
@@ -76,6 +76,8 @@ enum {
|
|
IPMI_LANP_RMCP_CIPHER_SUPPORT,
|
|
IPMI_LANP_RMCP_CIPHERS,
|
|
IPMI_LANP_RMCP_PRIV_LEVELS,
|
|
+ IPMI_LANP_VLAN_TAGS,
|
|
+ IPMI_LANP_BAD_PASS_THRESH,
|
|
IPMI_LANP_OEM_ALERT_STRING=96,
|
|
IPMI_LANP_ALERT_RETRY=97,
|
|
IPMI_LANP_UTC_OFFSET=98,
|
|
@@ -92,38 +94,39 @@ static struct lan_param {
|
|
uint8_t * data;
|
|
int data_len;
|
|
} ipmi_lan_params[] __attribute__((unused)) = {
|
|
- { IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress" },
|
|
- { IPMI_LANP_AUTH_TYPE, 1, "Auth Type Support" },
|
|
- { IPMI_LANP_AUTH_TYPE_ENABLE, 5, "Auth Type Enable" },
|
|
- { IPMI_LANP_IP_ADDR, 4, "IP Address" },
|
|
- { IPMI_LANP_IP_ADDR_SRC, 1, "IP Address Source" },
|
|
- { IPMI_LANP_MAC_ADDR, 6, "MAC Address" }, /* 5 */
|
|
- { IPMI_LANP_SUBNET_MASK, 4, "Subnet Mask" },
|
|
- { IPMI_LANP_IP_HEADER, 3, "IP Header" },
|
|
- { IPMI_LANP_PRI_RMCP_PORT, 2, "Primary RMCP Port" },
|
|
- { IPMI_LANP_SEC_RMCP_PORT, 2, "Secondary RMCP Port" },
|
|
- { IPMI_LANP_BMC_ARP, 1, "BMC ARP Control" }, /* 10 */
|
|
- { IPMI_LANP_GRAT_ARP, 1, "Gratituous ARP Intrvl" },
|
|
- { IPMI_LANP_DEF_GATEWAY_IP, 4, "Default Gateway IP" },
|
|
- { IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC" },
|
|
- { IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP" },
|
|
- { IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC" }, /* 15 */
|
|
- { IPMI_LANP_SNMP_STRING, 18, "SNMP Community String" },
|
|
- { IPMI_LANP_NUM_DEST, 1, "Number of Destinations"},
|
|
- { IPMI_LANP_DEST_TYPE, 4, "Destination Type" },
|
|
- { IPMI_LANP_DEST_ADDR, 13, "Destination Addresses" },
|
|
- { IPMI_LANP_VLAN_ID, 2, "802.1q VLAN ID" }, /* 20 */
|
|
- { IPMI_LANP_VLAN_PRIORITY, 1, "802.1q VLAN Priority" },
|
|
- { IPMI_LANP_RMCP_CIPHER_SUPPORT,1, "RMCP+ Cipher Suite Count" },
|
|
- { IPMI_LANP_RMCP_CIPHERS, 16, "RMCP+ Cipher Suites" },
|
|
- { IPMI_LANP_RMCP_PRIV_LEVELS, 9, "Cipher Suite Priv Max" },
|
|
- { IPMI_LANP_OEM_ALERT_STRING, 28, "OEM Alert String" }, /* 25 */
|
|
- { IPMI_LANP_ALERT_RETRY, 1, "Alert Retry Algorithm" },
|
|
- { IPMI_LANP_UTC_OFFSET, 3, "UTC Offset" },
|
|
- { IPMI_LANP_DHCP_SERVER_IP, 4, "DHCP Server IP" },
|
|
- { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC" },
|
|
- { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable" }, /* 30 */
|
|
- { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode" },
|
|
+ { IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress", NULL, 0 },
|
|
+ { IPMI_LANP_AUTH_TYPE, 1, "Auth Type Support", NULL, 0 },
|
|
+ { IPMI_LANP_AUTH_TYPE_ENABLE, 5, "Auth Type Enable", NULL, 0 },
|
|
+ { IPMI_LANP_IP_ADDR, 4, "IP Address", NULL, 0 },
|
|
+ { IPMI_LANP_IP_ADDR_SRC, 1, "IP Address Source", NULL, 0 },
|
|
+ { IPMI_LANP_MAC_ADDR, 6, "MAC Address", NULL, 0 }, /* 5 */
|
|
+ { IPMI_LANP_SUBNET_MASK, 4, "Subnet Mask", NULL, 0 },
|
|
+ { IPMI_LANP_IP_HEADER, 3, "IP Header", NULL, 0 },
|
|
+ { IPMI_LANP_PRI_RMCP_PORT, 2, "Primary RMCP Port", NULL, 0 },
|
|
+ { IPMI_LANP_SEC_RMCP_PORT, 2, "Secondary RMCP Port", NULL, 0 },
|
|
+ { IPMI_LANP_BMC_ARP, 1, "BMC ARP Control", NULL, 0}, /* 10 */
|
|
+ { IPMI_LANP_GRAT_ARP, 1, "Gratituous ARP Intrvl", NULL, 0 },
|
|
+ { IPMI_LANP_DEF_GATEWAY_IP, 4, "Default Gateway IP", NULL, 0 },
|
|
+ { IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC", NULL, 0 },
|
|
+ { IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP", NULL, 0 },
|
|
+ { IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC", NULL, 0 }, /* 15 */
|
|
+ { IPMI_LANP_SNMP_STRING, 18, "SNMP Community String", NULL, 0 },
|
|
+ { IPMI_LANP_NUM_DEST, 1, "Number of Destinations", NULL, 0 },
|
|
+ { IPMI_LANP_DEST_TYPE, 4, "Destination Type", NULL, 0 },
|
|
+ { IPMI_LANP_DEST_ADDR, 13, "Destination Addresses", NULL, 0 },
|
|
+ { IPMI_LANP_VLAN_ID, 2, "802.1q VLAN ID", NULL, 0 }, /* 20 */
|
|
+ { IPMI_LANP_VLAN_PRIORITY, 1, "802.1q VLAN Priority", NULL, 0 },
|
|
+ { IPMI_LANP_RMCP_CIPHER_SUPPORT,1, "RMCP+ Cipher Suite Count", NULL, 0 },
|
|
+ { IPMI_LANP_RMCP_CIPHERS, 16, "RMCP+ Cipher Suites", NULL, 0 },
|
|
+ { IPMI_LANP_RMCP_PRIV_LEVELS, 9, "Cipher Suite Priv Max", NULL, 0 },
|
|
+ { IPMI_LANP_BAD_PASS_THRESH, 6, "Bad Password Threshold", NULL, 0 },
|
|
+ { IPMI_LANP_OEM_ALERT_STRING, 28, "OEM Alert String", NULL, 0 }, /* 25 */
|
|
+ { IPMI_LANP_ALERT_RETRY, 1, "Alert Retry Algorithm", NULL, 0 },
|
|
+ { IPMI_LANP_UTC_OFFSET, 3, "UTC Offset", NULL, 0 },
|
|
+ { IPMI_LANP_DHCP_SERVER_IP, 4, "DHCP Server IP", NULL, 0 },
|
|
+ { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC", NULL, 0},
|
|
+ { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable", NULL, 0 }, /* 30 */
|
|
+ { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode", NULL, 0 },
|
|
{ -1 }
|
|
};
|
|
|
|
diff --git a/include/ipmitool/ipmi_mc.h b/include/ipmitool/ipmi_mc.h
|
|
index 5546a3a..a840f78 100644
|
|
--- a/include/ipmitool/ipmi_mc.h
|
|
+++ b/include/ipmitool/ipmi_mc.h
|
|
@@ -157,6 +157,9 @@ struct ipm_get_watchdog_rsp {
|
|
#define IPMI_SYSINFO_SET0_SIZE 14
|
|
#define IPMI_SYSINFO_SETN_SIZE 16
|
|
|
|
+/* System Information "Parameter selector" values: */
|
|
+#define IPMI_SYSINFO_SET_STATE 0x00
|
|
+#define IPMI_SYSINFO_SYSTEM_FW_VERSION 0x01
|
|
#define IPMI_SYSINFO_HOSTNAME 0x02
|
|
#define IPMI_SYSINFO_PRIMARY_OS_NAME 0x03
|
|
#define IPMI_SYSINFO_OS_NAME 0x04
|
|
diff --git a/include/ipmitool/ipmi_sel.h b/include/ipmitool/ipmi_sel.h
|
|
index cacdb2d..53a8c1f 100644
|
|
--- a/include/ipmitool/ipmi_sel.h
|
|
+++ b/include/ipmitool/ipmi_sel.h
|
|
@@ -690,41 +690,41 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu
|
|
};
|
|
|
|
static uint16_t supermicro_x9dal[] = {
|
|
- 0x0635
|
|
+ 0x0635, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_x9db[] = {
|
|
- 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637
|
|
+ 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_x9sb[] = {
|
|
- 0x0651
|
|
+ 0x0651, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_x9[] = {
|
|
- 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651
|
|
+ 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_b8[] = {
|
|
- 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e
|
|
+ 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_h8[] = {
|
|
0xa111, 0x0408, 0x0811, 0x1411, 0x0911, 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11,
|
|
0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611,
|
|
0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211,
|
|
- 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811
|
|
+ 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_p8[] = {
|
|
- 0x6480, 0x7380, 0x6280, 0x7480, 0x5980
|
|
+ 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_x8[] = {
|
|
0xa880, 0x0403, 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006,
|
|
0x040a, 0xf280, 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614,
|
|
0x060c, 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e,
|
|
- 0x061a, 0xf580, 0x062e, 0x0009
|
|
+ 0x061a, 0xf580, 0x062e, 0x0009, 0xFFFF
|
|
};
|
|
|
|
static uint16_t supermicro_X8[] = {
|
|
@@ -736,7 +736,7 @@ static uint16_t supermicro_X8[] = {
|
|
0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f,
|
|
0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x060c, 0x0003, 0x040b,
|
|
0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e,
|
|
- 0x0009
|
|
+ 0x0009, 0xFFFF
|
|
};
|
|
|
|
int ipmi_sel_main(struct ipmi_intf *, int, char **);
|
|
diff --git a/include/ipmitool/ipmi_user.h b/include/ipmitool/ipmi_user.h
|
|
index 4a8e481..fd727ca 100644
|
|
--- a/include/ipmitool/ipmi_user.h
|
|
+++ b/include/ipmitool/ipmi_user.h
|
|
@@ -38,58 +38,46 @@
|
|
#endif
|
|
#include <ipmitool/ipmi.h>
|
|
|
|
+#define IPMI_PASSWORD_DISABLE_USER 0x00
|
|
+#define IPMI_PASSWORD_ENABLE_USER 0x01
|
|
+#define IPMI_PASSWORD_SET_PASSWORD 0x02
|
|
+#define IPMI_PASSWORD_TEST_PASSWORD 0x03
|
|
|
|
-/*
|
|
- * The GET USER ACCESS response from table 22-32 of the IPMI v2.0 spec
|
|
- */
|
|
-struct user_access_rsp {
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved1 : 2;
|
|
- uint8_t maximum_ids : 6;
|
|
-#else
|
|
- uint8_t maximum_ids : 6;
|
|
- uint8_t __reserved1 : 2;
|
|
-#endif
|
|
-
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved2 : 2;
|
|
- uint8_t enabled_user_count : 6;
|
|
-#else
|
|
- uint8_t enabled_user_count : 6;
|
|
- uint8_t __reserved2 : 2;
|
|
-#endif
|
|
-
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved3 : 2;
|
|
- uint8_t fixed_name_count : 6;
|
|
-#else
|
|
- uint8_t fixed_name_count : 6;
|
|
- uint8_t __reserved3 : 2;
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-#if WORDS_BIGENDIAN
|
|
- uint8_t __reserved4 : 1;
|
|
- uint8_t no_callin_access : 1;
|
|
- uint8_t link_auth_access : 1;
|
|
- uint8_t ipmi_messaging_access : 1;
|
|
- uint8_t channel_privilege_limit : 4;
|
|
-#else
|
|
- uint8_t channel_privilege_limit : 4;
|
|
- uint8_t ipmi_messaging_access : 1;
|
|
- uint8_t link_auth_access : 1;
|
|
- uint8_t no_callin_access : 1;
|
|
- uint8_t __reserved4 : 1;
|
|
-#endif
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
+#define IPMI_USER_ENABLE_UNSPECIFIED 0x00
|
|
+#define IPMI_USER_ENABLE_ENABLED 0x40
|
|
+#define IPMI_USER_ENABLE_DISABLED 0x80
|
|
+#define IPMI_USER_ENABLE_RESERVED 0xC0
|
|
|
|
+/* (22.27) Get and (22.26) Set User Access */
|
|
+struct user_access_t {
|
|
+ uint8_t callin_callback;
|
|
+ uint8_t channel;
|
|
+ uint8_t enabled_user_ids;
|
|
+ uint8_t enable_status;
|
|
+ uint8_t fixed_user_ids;
|
|
+ uint8_t ipmi_messaging;
|
|
+ uint8_t link_auth;
|
|
+ uint8_t max_user_ids;
|
|
+ uint8_t privilege_limit;
|
|
+ uint8_t session_limit;
|
|
+ uint8_t user_id;
|
|
+};
|
|
|
|
+/* (22.29) Get User Name */
|
|
+struct user_name_t {
|
|
+ uint8_t user_id;
|
|
+ uint8_t user_name[17];
|
|
+};
|
|
|
|
int ipmi_user_main(struct ipmi_intf *, int, char **);
|
|
+int _ipmi_get_user_access(struct ipmi_intf *intf,
|
|
+ struct user_access_t *user_access_rsp);
|
|
+int _ipmi_get_user_name(struct ipmi_intf *intf, struct user_name_t *user_name);
|
|
+int _ipmi_set_user_access(struct ipmi_intf *intf,
|
|
+ struct user_access_t *user_access_req,
|
|
+ uint8_t change_priv_limit_only);
|
|
+int _ipmi_set_user_password(struct ipmi_intf *intf,
|
|
+ uint8_t user_id, uint8_t operation,
|
|
+ const char *password, uint8_t is_twenty_byte);
|
|
|
|
#endif /* IPMI_USER_H */
|
|
diff --git a/include/ipmitool/ipmi_vita.h b/include/ipmitool/ipmi_vita.h
|
|
new file mode 100644
|
|
index 0000000..71d471a
|
|
--- /dev/null
|
|
+++ b/include/ipmitool/ipmi_vita.h
|
|
@@ -0,0 +1,49 @@
|
|
+/*
|
|
+ * Copyright (c) Pigeon Point Systems. All right reserved
|
|
+ */
|
|
+
|
|
+#ifndef _IPMI_VITA_H_
|
|
+#define _IPMI_VITA_H_
|
|
+
|
|
+/* VITA 46.11 commands */
|
|
+#define VITA_GET_VSO_CAPABILITIES_CMD 0x00
|
|
+#define VITA_FRU_CONTROL_CMD 0x04
|
|
+#define VITA_GET_FRU_LED_PROPERTIES_CMD 0x05
|
|
+#define VITA_GET_LED_COLOR_CAPABILITIES_CMD 0x06
|
|
+#define VITA_SET_FRU_LED_STATE_CMD 0x07
|
|
+#define VITA_GET_FRU_LED_STATE_CMD 0x08
|
|
+#define VITA_SET_FRU_STATE_POLICY_BITS_CMD 0x0A
|
|
+#define VITA_GET_FRU_STATE_POLICY_BITS_CMD 0x0B
|
|
+#define VITA_SET_FRU_ACTIVATION_CMD 0x0C
|
|
+#define VITA_GET_FRU_ADDRESS_INFO_CMD 0x40
|
|
+
|
|
+/* VITA 46.11 site types */
|
|
+#define VITA_FRONT_VPX_MODULE 0x00
|
|
+#define VITA_POWER_ENTRY 0x01
|
|
+#define VITA_CHASSIS_FRU 0x02
|
|
+#define VITA_DEDICATED_CHMC 0x03
|
|
+#define VITA_FAN_TRAY 0x04
|
|
+#define VITA_FAN_TRAY_FILTER 0x05
|
|
+#define VITA_ALARM_PANEL 0x06
|
|
+#define VITA_XMC 0x07
|
|
+#define VITA_VPX_RTM 0x09
|
|
+#define VITA_FRONT_VME_MODULE 0x0A
|
|
+#define VITA_FRONT_VXS_MODULE 0x0B
|
|
+#define VITA_POWER_SUPPLY 0x0C
|
|
+#define VITA_FRONT_VITA62_MODULE 0x0D
|
|
+#define VITA_71_MODULE 0x0E
|
|
+#define VITA_FMC 0x0F
|
|
+
|
|
+
|
|
+#define GROUP_EXT_VITA 0x03
|
|
+
|
|
+extern uint8_t
|
|
+vita_discover(struct ipmi_intf *intf);
|
|
+
|
|
+extern uint8_t
|
|
+ipmi_vita_ipmb_address(struct ipmi_intf *intf);
|
|
+
|
|
+extern int
|
|
+ipmi_vita_main(struct ipmi_intf * intf, int argc, char ** argv);
|
|
+
|
|
+#endif /* _IPMI_VITA_H_ */
|
|
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
|
index d878b11..2a316db 100644
|
|
--- a/lib/Makefile.am
|
|
+++ b/lib/Makefile.am
|
|
@@ -39,7 +39,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
|
|
ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \
|
|
ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \
|
|
ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \
|
|
- ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c \
|
|
+ ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c ipmi_vita.c \
|
|
../src/plugins/lan/md5.c ../src/plugins/lan/md5.h
|
|
|
|
libipmitool_la_LDFLAGS = -export-dynamic
|
|
diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c
|
|
index 91ae117..912b211 100644
|
|
--- a/lib/dimm_spd.c
|
|
+++ b/lib/dimm_spd.c
|
|
@@ -867,9 +867,11 @@ ipmi_spd_print(uint8_t *spd_data, int len)
|
|
int sdram_width = 0;
|
|
int mem_size = 0;
|
|
int lrank_dimm;
|
|
+ uint32_t year;
|
|
+ uint32_t week;
|
|
|
|
- if (len < 148)
|
|
- return -1; /* we need first 91 bytes to do our thing */
|
|
+ if (len < 348)
|
|
+ return -1;
|
|
|
|
/* "Logical rank" referes to the individually addressable die
|
|
* in a 3DS stack and has no meaning for monolithic or
|
|
@@ -879,7 +881,7 @@ ipmi_spd_print(uint8_t *spd_data, int len)
|
|
* rank per package rank.
|
|
*/
|
|
lrank_dimm = (spd_data[12]>>3&0x3) + 1; /* Number of Package Ranks per DIMM */
|
|
- if ((spd_data[6] & 0x3) == 0x10) { /* 3DS package Type */
|
|
+ if ((spd_data[6] & 0x3) == 0x2) { /* 3DS package Type */
|
|
lrank_dimm *= ((spd_data[6]>>4)&0x3) + 1; /* Die Count */
|
|
}
|
|
sdram_cap = ldexp(256,(spd_data[4]&15));
|
|
@@ -931,8 +933,8 @@ ipmi_spd_print(uint8_t *spd_data, int len)
|
|
|
|
}
|
|
|
|
- u_int year = (spd_data[323]>>4)*10 + spd_data[323]&15;
|
|
- u_int week = (spd_data[324]>>4)*10 + spd_data[324]&15;
|
|
+ year = ((spd_data[323] >> 4) * 10) + (spd_data[323] & 15);
|
|
+ week = ((spd_data[324]>>4) * 10) + (spd_data[324] & 15);
|
|
printf(" Manufacture Date : year %4d week %2d\n",
|
|
2000 + year, week);
|
|
|
|
@@ -948,6 +950,9 @@ ipmi_spd_print(uint8_t *spd_data, int len)
|
|
}
|
|
else
|
|
{
|
|
+ if (len < 100) {
|
|
+ return (-1);
|
|
+ }
|
|
ii = (spd_data[3] & 0x0f) + (spd_data[4] & 0x0f) - 17;
|
|
k = ((spd_data[5] & 0x7) + 1) * spd_data[17];
|
|
|
|
@@ -1064,7 +1069,6 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
|
|
offset = 0;
|
|
memset(spd_data, 0, fru.size);
|
|
do {
|
|
- int i;
|
|
msg_data[0] = id;
|
|
msg_data[1] = offset & 0xFF;
|
|
msg_data[2] = offset >> 8;
|
|
diff --git a/lib/helper.c b/lib/helper.c
|
|
index 95d641e..b9316c4 100644
|
|
--- a/lib/helper.c
|
|
+++ b/lib/helper.c
|
|
@@ -29,6 +29,7 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _POSIX_SOURCE
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
@@ -671,6 +672,43 @@ ipmi_start_daemon(struct ipmi_intf *intf)
|
|
dup(fd);
|
|
}
|
|
|
|
+/* eval_ccode - evaluate return value of _ipmi_* functions and print error error
|
|
+ * message, if conditions are met.
|
|
+ *
|
|
+ * @ccode - return value of _ipmi_* function.
|
|
+ *
|
|
+ * returns - 0 if ccode is 0, otherwise (-1) and error might get printed-out.
|
|
+ */
|
|
+int
|
|
+eval_ccode(const int ccode)
|
|
+{
|
|
+ if (ccode == 0) {
|
|
+ return 0;
|
|
+ } else if (ccode < 0) {
|
|
+ switch (ccode) {
|
|
+ case (-1):
|
|
+ lprintf(LOG_ERR, "IPMI response is NULL.");
|
|
+ break;
|
|
+ case (-2):
|
|
+ lprintf(LOG_ERR, "Unexpected data length received.");
|
|
+ break;
|
|
+ case (-3):
|
|
+ lprintf(LOG_ERR, "Invalid function parameter.");
|
|
+ break;
|
|
+ case (-4):
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure.");
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return (-1);
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "IPMI command failed: %s",
|
|
+ val2str(ccode, completion_code_vals));
|
|
+ return (-1);
|
|
+ }
|
|
+}
|
|
+
|
|
/* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
|
|
* on error.
|
|
* FRU ID range: <0..255>
|
|
@@ -700,9 +738,9 @@ is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr)
|
|
/* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is
|
|
* printed on error.
|
|
*
|
|
- * 6.3 Channel Numbers, p. 45, IPMIv2 spec.
|
|
- * Valid channel numbers are: <0..7>, <E-F>
|
|
- * Reserved channel numbers: <8-D>
|
|
+ * 6.3 Channel Numbers, p. 49, IPMIv2 spec. rev1.1
|
|
+ * Valid channel numbers are: <0x0..0xB>, <0xE-0xF>
|
|
+ * Reserved channel numbers: <0xC-0xD>
|
|
*
|
|
* @argv_ptr: source string to convert from; usually argv
|
|
* @channel_ptr: pointer where to store result
|
|
@@ -719,14 +757,14 @@ is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr)
|
|
return (-1);
|
|
}
|
|
if ((str2uchar(argv_ptr, channel_ptr) == 0)
|
|
- && ((*channel_ptr >= 0x0 && *channel_ptr <= 0x7)
|
|
+ && (*channel_ptr <= 0xB
|
|
|| (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) {
|
|
return 0;
|
|
}
|
|
lprintf(LOG_ERR,
|
|
"Given Channel number '%s' is either invalid or out of range.",
|
|
argv_ptr);
|
|
- lprintf(LOG_ERR, "Channel number must be from ranges: <0..7>, <0xE..0xF>");
|
|
+ lprintf(LOG_ERR, "Channel number must be from ranges: <0x0..0xB>, <0xE..0xF>");
|
|
return (-1);
|
|
}
|
|
|
|
@@ -760,6 +798,36 @@ is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
|
|
return (-1);
|
|
}
|
|
|
|
+/* is_ipmi_user_priv_limit - check whether given value is valid User Privilege
|
|
+ * Limit, eg. IPMI v2 spec, 22.27 Get User Access Command.
|
|
+ *
|
|
+ * @priv_limit: User Privilege Limit
|
|
+ *
|
|
+ * returns 0 if Priv Limit is valid
|
|
+ * returns (-1) when Priv Limit is invalid
|
|
+ */
|
|
+int
|
|
+is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr)
|
|
+{
|
|
+ if (!argv_ptr || !ipmi_priv_limit_ptr) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "is_ipmi_user_priv_limit(): invalid argument(s).");
|
|
+ return (-1);
|
|
+ }
|
|
+ if ((str2uchar(argv_ptr, ipmi_priv_limit_ptr) != 0)
|
|
+ || ((*ipmi_priv_limit_ptr < 0x01
|
|
+ || *ipmi_priv_limit_ptr > 0x05)
|
|
+ && *ipmi_priv_limit_ptr != 0x0F)) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given Privilege Limit '%s' is invalid.",
|
|
+ argv_ptr);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Privilege Limit is limited to <0x1..0x5> and <0xF>.");
|
|
+ return (-1);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
uint16_t
|
|
ipmi_get_oem_id(struct ipmi_intf *intf)
|
|
{
|
|
diff --git a/lib/hpm2.c b/lib/hpm2.c
|
|
index 6cb2f80..6420629 100644
|
|
--- a/lib/hpm2.c
|
|
+++ b/lib/hpm2.c
|
|
@@ -213,8 +213,8 @@ int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf,
|
|
/* send */
|
|
rsp = intf->sendrecv(intf, &req);
|
|
|
|
- if (rsp) {
|
|
- lprintf(LOG_NOTICE, "Error sending request");
|
|
+ if (!rsp) {
|
|
+ lprintf(LOG_NOTICE, "Error sending request.");
|
|
return -1;
|
|
}
|
|
|
|
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c
|
|
index 43db338..95017b8 100644
|
|
--- a/lib/ipmi_channel.c
|
|
+++ b/lib/ipmi_channel.c
|
|
@@ -50,11 +50,176 @@
|
|
#include <ipmitool/ipmi_channel.h>
|
|
#include <ipmitool/ipmi_strings.h>
|
|
#include <ipmitool/ipmi_constants.h>
|
|
+#include <ipmitool/ipmi_user.h>
|
|
|
|
extern int csv_output;
|
|
extern int verbose;
|
|
|
|
-void printf_channel_usage (void);
|
|
+void printf_channel_usage(void);
|
|
+
|
|
+/* _ipmi_get_channel_access - Get Channel Access for given channel. Results are
|
|
+ * stored into passed struct.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel_access - ptr to channel_access_t with Channel set.
|
|
+ * @get_volatile_settings - get volatile if != 0, else non-volatile settings.
|
|
+ *
|
|
+ * returns - negative number means error, positive is a ccode.
|
|
+ */
|
|
+int
|
|
+_ipmi_get_channel_access(struct ipmi_intf *intf,
|
|
+ struct channel_access_t *channel_access,
|
|
+ uint8_t get_volatile_settings)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req = {0};
|
|
+ uint8_t data[2];
|
|
+
|
|
+ if (channel_access == NULL) {
|
|
+ return (-3);
|
|
+ }
|
|
+ data[0] = channel_access->channel & 0x0F;
|
|
+ /* volatile - 0x80; non-volatile - 0x40 */
|
|
+ data[1] = get_volatile_settings ? 0x80 : 0x40;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_CHANNEL_ACCESS;
|
|
+ req.msg.data = data;
|
|
+ req.msg.data_len = 2;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ return rsp->ccode;
|
|
+ } else if (rsp->data_len != 2) {
|
|
+ return (-2);
|
|
+ }
|
|
+ channel_access->alerting = rsp->data[0] & 0x20;
|
|
+ channel_access->per_message_auth = rsp->data[0] & 0x10;
|
|
+ channel_access->user_level_auth = rsp->data[0] & 0x08;
|
|
+ channel_access->access_mode = rsp->data[0] & 0x07;
|
|
+ channel_access->privilege_limit = rsp->data[1] & 0x0F;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* _ipmi_get_channel_info - Get Channel Info for given channel. Results are
|
|
+ * stored into passed struct.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel_info - ptr to channel_info_t with Channel set.
|
|
+ *
|
|
+ * returns - negative number means error, positive is a ccode.
|
|
+ */
|
|
+int
|
|
+_ipmi_get_channel_info(struct ipmi_intf *intf,
|
|
+ struct channel_info_t *channel_info)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req = {0};
|
|
+ uint8_t data[1];
|
|
+
|
|
+ if (channel_info == NULL) {
|
|
+ return (-3);
|
|
+ }
|
|
+ data[0] = channel_info->channel & 0x0F;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_CHANNEL_INFO;
|
|
+ req.msg.data = data;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ return rsp->ccode;
|
|
+ } else if (rsp->data_len != 9) {
|
|
+ return (-2);
|
|
+ }
|
|
+ channel_info->channel = rsp->data[0] & 0x0F;
|
|
+ channel_info->medium = rsp->data[1] & 0x7F;
|
|
+ channel_info->protocol = rsp->data[2] & 0x1F;
|
|
+ channel_info->session_support = rsp->data[3] & 0xC0;
|
|
+ channel_info->active_sessions = rsp->data[3] & 0x3F;
|
|
+ memcpy(channel_info->vendor_id, &rsp->data[4],
|
|
+ sizeof(channel_info->vendor_id));
|
|
+ memcpy(channel_info->aux_info, &rsp->data[7],
|
|
+ sizeof(channel_info->aux_info));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* _ipmi_set_channel_access - Set Channel Access values for given channel.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel_access - channel_access_t with desired values and channel set.
|
|
+ * @access_option:
|
|
+ * - 0 = don't set/change Channel Access
|
|
+ * - 1 = set non-volatile settings of Channel Access
|
|
+ * - 2 = set volatile settings of Channel Access
|
|
+ * @privilege_option:
|
|
+ * - 0 = don't set/change Privilege Level Limit
|
|
+ * - 1 = set non-volatile settings of Privilege Limit
|
|
+ * - 2 = set volatile settings of Privilege Limit
|
|
+ *
|
|
+ * returns - negative number means error, positive is a ccode. See IPMI
|
|
+ * specification for further information on ccodes for Set Channel Access.
|
|
+ * 0x82 - set not supported on selected channel, eg. session-less channel.
|
|
+ * 0x83 - access mode not supported
|
|
+ */
|
|
+int
|
|
+_ipmi_set_channel_access(struct ipmi_intf *intf,
|
|
+ struct channel_access_t channel_access,
|
|
+ uint8_t access_option,
|
|
+ uint8_t privilege_option)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ uint8_t data[3];
|
|
+ /* Only values from <0..2> are accepted as valid. */
|
|
+ if (access_option > 2 || privilege_option > 2) {
|
|
+ return (-3);
|
|
+ }
|
|
+
|
|
+ memset(&data, 0, sizeof(data));
|
|
+ data[0] = channel_access.channel & 0x0F;
|
|
+ data[1] = (access_option << 6);
|
|
+ if (channel_access.alerting) {
|
|
+ data[1] |= 0x20;
|
|
+ }
|
|
+ if (channel_access.per_message_auth) {
|
|
+ data[1] |= 0x10;
|
|
+ }
|
|
+ if (channel_access.user_level_auth) {
|
|
+ data[1] |= 0x08;
|
|
+ }
|
|
+ data[1] |= (channel_access.access_mode & 0x07);
|
|
+ data[2] = (privilege_option << 6);
|
|
+ data[2] |= (channel_access.privilege_limit & 0x0F);
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_SET_CHANNEL_ACCESS;
|
|
+ req.msg.data = data;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ return (-1);
|
|
+ }
|
|
+ return rsp->ccode;
|
|
+}
|
|
+
|
|
+static const char *
|
|
+iana_string(uint32_t iana)
|
|
+{
|
|
+ static char s[10];
|
|
+
|
|
+ if (iana) {
|
|
+ sprintf(s, "%06x", iana);
|
|
+ return s;
|
|
+ } else {
|
|
+ return "N/A";
|
|
+ }
|
|
+}
|
|
|
|
/**
|
|
* ipmi_1_5_authtypes
|
|
@@ -68,8 +233,7 @@ ipmi_1_5_authtypes(uint8_t n)
|
|
uint32_t i;
|
|
static char supportedTypes[128];
|
|
|
|
- bzero(supportedTypes, 128);
|
|
-
|
|
+ memset(supportedTypes, 0, sizeof(supportedTypes));
|
|
for (i = 0; ipmi_authtype_vals[i].val != 0; i++) {
|
|
if (n & ipmi_authtype_vals[i].val) {
|
|
strcat(supportedTypes, ipmi_authtype_vals[i].str);
|
|
@@ -80,7 +244,11 @@ ipmi_1_5_authtypes(uint8_t n)
|
|
return supportedTypes;
|
|
}
|
|
|
|
-
|
|
+uint8_t
|
|
+ipmi_current_channel_medium(struct ipmi_intf *intf)
|
|
+{
|
|
+ return ipmi_get_channel_medium(intf, 0xE);
|
|
+}
|
|
|
|
/**
|
|
* ipmi_get_channel_auth_cap
|
|
@@ -89,27 +257,26 @@ ipmi_1_5_authtypes(uint8_t n)
|
|
* -1 on failure
|
|
*/
|
|
int
|
|
-ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
|
- uint8_t channel,
|
|
- uint8_t priv)
|
|
+ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
+ struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
struct get_channel_auth_cap_rsp auth_cap;
|
|
uint8_t msg_data[2];
|
|
|
|
- msg_data[0] = channel | 0x80; // Ask for IPMI v2 data as well
|
|
+ /* Ask for IPMI v2 data as well */
|
|
+ msg_data[0] = channel | 0x80;
|
|
msg_data[1] = priv;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; // 0x06
|
|
- req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
|
|
- req.msg.data = msg_data;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP;
|
|
+ req.msg.data = msg_data;
|
|
req.msg.data_len = 2;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
|
|
- if ((rsp == NULL) || (rsp->ccode > 0)) {
|
|
+ if ((rsp == NULL) || (rsp->ccode > 0)) {
|
|
/*
|
|
* It's very possible that this failed because we asked for IPMI v2 data
|
|
* Ask again, without requesting IPMI v2 data
|
|
@@ -119,12 +286,12 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Unable to Get Channel Authentication Capabilities");
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
if (rsp->ccode > 0) {
|
|
lprintf(LOG_ERR, "Get Channel Authentication Capabilities failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
}
|
|
|
|
@@ -135,9 +302,10 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
|
printf("IPMI v1.5 auth types : %s\n",
|
|
ipmi_1_5_authtypes(auth_cap.enabled_auth_types));
|
|
|
|
- if (auth_cap.v20_data_available)
|
|
+ if (auth_cap.v20_data_available) {
|
|
printf("KG status : %s\n",
|
|
(auth_cap.kg_status) ? "non-zero" : "default (all zeroes)");
|
|
+ }
|
|
|
|
printf("Per message authentication : %sabled\n",
|
|
(auth_cap.per_message_auth) ? "dis" : "en");
|
|
@@ -174,118 +342,252 @@ ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
|
return 0;
|
|
}
|
|
|
|
-
|
|
-
|
|
-/**
|
|
- * ipmi_get_channel_info
|
|
- *
|
|
- * returns 0 on success
|
|
- * -1 on failure
|
|
- *
|
|
- */
|
|
-int
|
|
-ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel)
|
|
+static int
|
|
+ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
|
|
+ uint8_t channel)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
+ struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
- uint8_t rqdata[2];
|
|
- uint8_t medium;
|
|
- struct get_channel_info_rsp channel_info;
|
|
- struct get_channel_access_rsp channel_access;
|
|
|
|
+ uint8_t rqdata[3];
|
|
+ uint32_t iana;
|
|
+ uint8_t auth_alg, integrity_alg, crypt_alg;
|
|
+ uint8_t cipher_suite_id;
|
|
+ uint8_t list_index = 0;
|
|
+ /* 0x40 sets * 16 bytes per set */
|
|
+ uint8_t cipher_suite_data[1024];
|
|
+ uint16_t offset = 0;
|
|
+ /* how much was returned, total */
|
|
+ uint16_t cipher_suite_data_length = 0;
|
|
+
|
|
+ memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
|
|
+
|
|
memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; // 0x06
|
|
- req.msg.cmd = IPMI_GET_CHANNEL_INFO; // 0x42
|
|
- req.msg.data = &channel;
|
|
- req.msg.data_len = 1;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES;
|
|
+ req.msg.data = rqdata;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ rqdata[0] = channel;
|
|
+ rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1);
|
|
+ /* Always ask for cipher suite format */
|
|
+ rqdata[2] = 0x80;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Info");
|
|
+ lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
|
|
return -1;
|
|
}
|
|
if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Info failed: %s",
|
|
+ lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return -1;
|
|
}
|
|
|
|
- memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp));
|
|
|
|
- printf("Channel 0x%x info:\n", channel_info.channel_number);
|
|
+ /*
|
|
+ * Grab the returned channel number once. We assume it's the same
|
|
+ * in future calls.
|
|
+ */
|
|
+ if (rsp->data_len >= 1) {
|
|
+ channel = rsp->data[0];
|
|
+ }
|
|
|
|
- printf(" Channel Medium Type : %s\n",
|
|
- val2str(channel_info.channel_medium, ipmi_channel_medium_vals));
|
|
+ while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) {
|
|
+ /*
|
|
+ * We got back cipher suite data -- store it.
|
|
+ * printf("copying data to offset %d\n", offset);
|
|
+ * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
|
|
+ */
|
|
+ memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
|
|
+ offset += rsp->data_len - 1;
|
|
+
|
|
+ /*
|
|
+ * Increment our list for the next call
|
|
+ */
|
|
+ ++list_index;
|
|
+ rqdata[2] = (rqdata[2] & 0x80) + list_index;
|
|
|
|
- printf(" Channel Protocol Type : %s\n",
|
|
- val2str(channel_info.channel_protocol, ipmi_channel_protocol_vals));
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
|
|
+ return -1;
|
|
+ }
|
|
+ if (rsp->ccode > 0) {
|
|
+ lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Copy last chunk */
|
|
+ if(rsp->data_len > 1) {
|
|
+ /*
|
|
+ * We got back cipher suite data -- store it.
|
|
+ * printf("copying data to offset %d\n", offset);
|
|
+ * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
|
|
+ */
|
|
+ memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
|
|
+ offset += rsp->data_len - 1;
|
|
+ }
|
|
+
|
|
+ /* We can chomp on all our data now. */
|
|
+ cipher_suite_data_length = offset;
|
|
+ offset = 0;
|
|
+
|
|
+ if (! csv_output) {
|
|
+ printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
|
|
+ }
|
|
+ while (offset < cipher_suite_data_length) {
|
|
+ if (cipher_suite_data[offset++] == 0xC0) {
|
|
+ /* standard type */
|
|
+ iana = 0;
|
|
+
|
|
+ /* Verify that we have at least a full record left; id + 3 algs */
|
|
+ if ((cipher_suite_data_length - offset) < 4) {
|
|
+ lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
|
|
+ return -1;
|
|
+ }
|
|
+ cipher_suite_id = cipher_suite_data[offset++];
|
|
+ } else if (cipher_suite_data[offset++] == 0xC1) {
|
|
+ /* OEM record type */
|
|
+ /* Verify that we have at least a full record left
|
|
+ * id + iana + 3 algs
|
|
+ */
|
|
+ if ((cipher_suite_data_length - offset) < 4) {
|
|
+ lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ cipher_suite_id = cipher_suite_data[offset++];
|
|
+
|
|
+ /* Grab the IANA */
|
|
+ iana =
|
|
+ cipher_suite_data[offset] |
|
|
+ (cipher_suite_data[offset + 1] << 8) |
|
|
+ (cipher_suite_data[offset + 2] << 16);
|
|
+ offset += 3;
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Bad start of record byte in cipher suite data");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Grab the algorithms for this cipher suite. I guess we can't be
|
|
+ * sure of what order they'll come in. Also, I suppose we default
|
|
+ * to the NONE algorithm if one were absent. This part of the spec is
|
|
+ * poorly written -- I have read the errata document. For now, I'm only
|
|
+ * allowing one algorithm per type (auth, integrity, crypt) because I
|
|
+ * don't I understand how it could be otherwise.
|
|
+ */
|
|
+ auth_alg = IPMI_AUTH_RAKP_NONE;
|
|
+ integrity_alg = IPMI_INTEGRITY_NONE;
|
|
+ crypt_alg = IPMI_CRYPT_NONE;
|
|
+
|
|
+ while (((cipher_suite_data[offset] & 0xC0) != 0xC0) &&
|
|
+ ((cipher_suite_data_length - offset) > 0))
|
|
+ {
|
|
+ switch (cipher_suite_data[offset] & 0xC0)
|
|
+ {
|
|
+ case 0x00:
|
|
+ /* Authentication algorithm specifier */
|
|
+ auth_alg = cipher_suite_data[offset++] & 0x3F;
|
|
+ break;
|
|
+ case 0x40:
|
|
+ /* Interity algorithm specifier */
|
|
+ integrity_alg = cipher_suite_data[offset++] & 0x3F;
|
|
+ break;
|
|
+ case 0x80:
|
|
+ /* Confidentiality algorithm specifier */
|
|
+ crypt_alg = cipher_suite_data[offset++] & 0x3F;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ /* We have everything we need to spit out a cipher suite record */
|
|
+ printf((csv_output? "%d,%s,%s,%s,%s\n" :
|
|
+ "%-4d %-7s %-15s %-15s %-15s\n"),
|
|
+ cipher_suite_id,
|
|
+ iana_string(iana),
|
|
+ val2str(auth_alg, ipmi_auth_algorithms),
|
|
+ val2str(integrity_alg, ipmi_integrity_algorithms),
|
|
+ val2str(crypt_alg, ipmi_encryption_algorithms));
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * ipmi_get_channel_info
|
|
+ *
|
|
+ * returns 0 on success
|
|
+ * -1 on failure
|
|
+ *
|
|
+ */
|
|
+int
|
|
+ipmi_get_channel_info(struct ipmi_intf *intf, uint8_t channel)
|
|
+{
|
|
+ struct channel_info_t channel_info = {0};
|
|
+ struct channel_access_t channel_access = {0};
|
|
+ int ccode = 0;
|
|
+
|
|
+ channel_info.channel = channel;
|
|
+ ccode = _ipmi_get_channel_info(intf, &channel_info);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Unable to Get Channel Info");
|
|
+ return (-1);
|
|
+ }
|
|
|
|
+ printf("Channel 0x%x info:\n", channel_info.channel);
|
|
+ printf(" Channel Medium Type : %s\n",
|
|
+ val2str(channel_info.medium,
|
|
+ ipmi_channel_medium_vals));
|
|
+ printf(" Channel Protocol Type : %s\n",
|
|
+ val2str(channel_info.protocol,
|
|
+ ipmi_channel_protocol_vals));
|
|
printf(" Session Support : ");
|
|
switch (channel_info.session_support) {
|
|
- case 0x0:
|
|
+ case IPMI_CHANNEL_SESSION_LESS:
|
|
printf("session-less\n");
|
|
break;
|
|
- case 0x1:
|
|
+ case IPMI_CHANNEL_SESSION_SINGLE:
|
|
printf("single-session\n");
|
|
break;
|
|
- case 0x2:
|
|
+ case IPMI_CHANNEL_SESSION_MULTI:
|
|
printf("multi-session\n");
|
|
break;
|
|
- case 0x3:
|
|
- default:
|
|
+ case IPMI_CHANNEL_SESSION_BASED:
|
|
printf("session-based\n");
|
|
break;
|
|
+ default:
|
|
+ printf("unknown\n");
|
|
+ break;
|
|
}
|
|
-
|
|
printf(" Active Session Count : %d\n",
|
|
channel_info.active_sessions);
|
|
-
|
|
printf(" Protocol Vendor ID : %d\n",
|
|
channel_info.vendor_id[0] |
|
|
channel_info.vendor_id[1] << 8 |
|
|
channel_info.vendor_id[2] << 16);
|
|
|
|
-
|
|
/* only proceed if this is LAN channel */
|
|
- medium = ipmi_get_channel_medium(intf, channel);
|
|
- if (medium != IPMI_CHANNEL_MEDIUM_LAN &&
|
|
- medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) {
|
|
+ if (channel_info.medium != IPMI_CHANNEL_MEDIUM_LAN
|
|
+ && channel_info.medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) {
|
|
return 0;
|
|
}
|
|
|
|
- memset(&req, 0, sizeof(req));
|
|
- rqdata[0] = channel & 0xf;
|
|
-
|
|
- /* get volatile settings */
|
|
-
|
|
- rqdata[1] = 0x80; /* 0x80=active */
|
|
- req.msg.netfn = IPMI_NETFN_APP; // 0x06
|
|
- req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; // 0x41
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 2;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
+ channel_access.channel = channel_info.channel;
|
|
+ ccode = _ipmi_get_channel_access(intf, &channel_access, 1);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
lprintf(LOG_ERR, "Unable to Get Channel Access (volatile)");
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Access (volatile) failed: %s",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
|
|
- memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
|
|
-
|
|
-
|
|
printf(" Volatile(active) Settings\n");
|
|
printf(" Alerting : %sabled\n",
|
|
- (channel_access.alerting) ? "dis" : "en");
|
|
+ (channel_access.alerting) ? "dis" : "en");
|
|
printf(" Per-message Auth : %sabled\n",
|
|
- (channel_access.per_message_auth) ? "dis" : "en");
|
|
+ (channel_access.per_message_auth) ? "dis" : "en");
|
|
printf(" User Level Auth : %sabled\n",
|
|
- (channel_access.user_level_auth) ? "dis" : "en");
|
|
-
|
|
+ (channel_access.user_level_auth) ? "dis" : "en");
|
|
printf(" Access Mode : ");
|
|
switch (channel_access.access_mode) {
|
|
case 0:
|
|
@@ -305,30 +607,22 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel)
|
|
break;
|
|
}
|
|
|
|
+ memset(&channel_access, 0, sizeof(channel_access));
|
|
+ channel_access.channel = channel_info.channel;
|
|
/* get non-volatile settings */
|
|
-
|
|
- rqdata[1] = 0x40; /* 0x40=non-volatile */
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
lprintf(LOG_ERR, "Unable to Get Channel Access (non-volatile)");
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Access (non-volatile) failed: %s",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
|
|
- memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
|
|
-
|
|
printf(" Non-Volatile Settings\n");
|
|
printf(" Alerting : %sabled\n",
|
|
- (channel_access.alerting) ? "dis" : "en");
|
|
+ (channel_access.alerting) ? "dis" : "en");
|
|
printf(" Per-message Auth : %sabled\n",
|
|
- (channel_access.per_message_auth) ? "dis" : "en");
|
|
+ (channel_access.per_message_auth) ? "dis" : "en");
|
|
printf(" User Level Auth : %sabled\n",
|
|
- (channel_access.user_level_auth) ? "dis" : "en");
|
|
-
|
|
+ (channel_access.user_level_auth) ? "dis" : "en");
|
|
printf(" Access Mode : ");
|
|
switch (channel_access.access_mode) {
|
|
case 0:
|
|
@@ -347,66 +641,79 @@ ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel)
|
|
printf("unknown\n");
|
|
break;
|
|
}
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
-static int
|
|
-ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
|
|
+/* ipmi_get_channel_medium - Return Medium of given IPMI Channel.
|
|
+ *
|
|
+ * @channel - IPMI Channel
|
|
+ *
|
|
+ * returns - IPMI Channel Medium, IPMI_CHANNEL_MEDIUM_RESERVED if ccode > 0,
|
|
+ * 0 on error.
|
|
+ */
|
|
+uint8_t
|
|
+ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req1, req2;
|
|
- uint8_t rqdata[2];
|
|
- struct get_user_access_rsp user_access;
|
|
- int curr_uid, max_uid = 0, init = 1;
|
|
-
|
|
- curr_uid = userid ? : 1;
|
|
-
|
|
- memset(&req1, 0, sizeof(req1));
|
|
- req1.msg.netfn = IPMI_NETFN_APP;
|
|
- req1.msg.cmd = IPMI_GET_USER_ACCESS;
|
|
- req1.msg.data = rqdata;
|
|
- req1.msg.data_len = 2;
|
|
-
|
|
- memset(&req2, 0, sizeof(req2));
|
|
- req2.msg.netfn = IPMI_NETFN_APP;
|
|
- req2.msg.cmd = IPMI_GET_USER_NAME;
|
|
- req2.msg.data = rqdata;
|
|
- req2.msg.data_len = 1;
|
|
-
|
|
- do
|
|
- {
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = curr_uid & 0x3f;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req1);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)",
|
|
- rqdata[0], rqdata[1]);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s",
|
|
- rqdata[0], rqdata[1],
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
+ struct channel_info_t channel_info = {0};
|
|
+ int ccode = 0;
|
|
|
|
- memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
|
|
-
|
|
- rqdata[0] = curr_uid & 0x3f;
|
|
+ channel_info.channel = channel;
|
|
+ ccode = _ipmi_get_channel_info(intf, &channel_info);
|
|
+ if (ccode == 0xCC) {
|
|
+ return IPMI_CHANNEL_MEDIUM_RESERVED;
|
|
+ } else if (ccode < 0 && eval_ccode(ccode) != 0) {
|
|
+ return 0;
|
|
+ } else if (ccode > 0) {
|
|
+ lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
|
+ val2str(ccode, completion_code_vals));
|
|
+ return IPMI_CHANNEL_MEDIUM_RESERVED;
|
|
+ }
|
|
+ lprintf(LOG_DEBUG, "Channel type: %s",
|
|
+ val2str(channel_info.medium, ipmi_channel_medium_vals));
|
|
+ return channel_info.medium;
|
|
+}
|
|
|
|
- rsp = intf->sendrecv(intf, &req2);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get User Name (id %d)", rqdata[0]);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get User Name (id %d) failed: %s",
|
|
- rqdata[0], val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+/* ipmi_get_user_access - Get User Access for given Channel and User or Users.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel - IPMI Channel we're getting access for
|
|
+ * @user_id - User ID. If 0 is passed, all IPMI users will be listed
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error
|
|
+ */
|
|
+static int
|
|
+ipmi_get_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id)
|
|
+{
|
|
+ struct user_access_t user_access;
|
|
+ struct user_name_t user_name;
|
|
+ int ccode = 0;
|
|
+ int curr_uid;
|
|
+ int init = 1;
|
|
+ int max_uid = 0;
|
|
+
|
|
+ curr_uid = user_id ? user_id : 1;
|
|
+ do {
|
|
+ memset(&user_access, 0, sizeof(user_access));
|
|
+ user_access.channel = channel;
|
|
+ user_access.user_id = curr_uid;
|
|
+ ccode = _ipmi_get_user_access(intf, &user_access);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Get User Access (channel %d id %d)",
|
|
+ channel, curr_uid);
|
|
+ return (-1);
|
|
}
|
|
|
|
+ memset(&user_name, 0, sizeof(user_name));
|
|
+ user_name.user_id = curr_uid;
|
|
+ ccode = _ipmi_get_user_name(intf, &user_name);
|
|
+ if (ccode == 0xCC) {
|
|
+ user_name.user_id = curr_uid;
|
|
+ memset(&user_name.user_name, '\0', 17);
|
|
+ } else if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Unable to Get User Name (id %d)", curr_uid);
|
|
+ return (-1);
|
|
+ }
|
|
if (init) {
|
|
printf("Maximum User IDs : %d\n", user_access.max_user_ids);
|
|
printf("Enabled User IDs : %d\n", user_access.enabled_user_ids);
|
|
@@ -416,7 +723,7 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
|
|
|
|
printf("\n");
|
|
printf("User ID : %d\n", curr_uid);
|
|
- printf("User Name : %s\n", rsp->data);
|
|
+ printf("User Name : %s\n", user_name.user_name);
|
|
printf("Fixed Name : %s\n",
|
|
(curr_uid <= user_access.fixed_user_ids) ? "Yes" : "No");
|
|
printf("Access Available : %s\n",
|
|
@@ -429,475 +736,196 @@ ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
|
|
val2str(user_access.privilege_limit, ipmi_privlvl_vals));
|
|
|
|
curr_uid ++;
|
|
-
|
|
- } while (!userid && curr_uid <= max_uid);
|
|
+ } while (!user_id && curr_uid <= max_uid);
|
|
|
|
return 0;
|
|
}
|
|
|
|
-static int
|
|
-ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv)
|
|
+/* ipmi_set_user_access - Query BMC for current Channel ACLs, parse CLI args
|
|
+ * and update current ACLs.
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error
|
|
+ */
|
|
+int
|
|
+ipmi_set_user_access(struct ipmi_intf *intf, int argc, char **argv)
|
|
{
|
|
- uint8_t channel, privilege_limit, userid;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t rqdata[2];
|
|
- struct get_user_access_rsp user_access;
|
|
- struct set_user_access_data set_access;
|
|
- int i;
|
|
-
|
|
- if ((argc < 3) || (strncmp(argv[0], "help", 4) == 0)) {
|
|
+ struct user_access_t user_access = {0};
|
|
+ int ccode = 0;
|
|
+ int i = 0;
|
|
+ uint8_t channel = 0;
|
|
+ uint8_t priv = 0;
|
|
+ uint8_t user_id = 0;
|
|
+ if (argc > 0 && strncmp(argv[0], "help", 4) == 0) {
|
|
printf_channel_usage();
|
|
return 0;
|
|
- }
|
|
-
|
|
- if (str2uchar(argv[0], &channel) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[0]);
|
|
+ } else if (argc < 3) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
+ printf_channel_usage();
|
|
return (-1);
|
|
}
|
|
- if (str2uchar(argv[1], &userid) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
|
|
+ if (is_ipmi_channel_num(argv[0], &channel) != 0
|
|
+ || is_ipmi_user_id(argv[1], &user_id) != 0) {
|
|
return (-1);
|
|
}
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = IPMI_GET_USER_ACCESS;
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 2;
|
|
-
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = userid & 0x3f;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)",
|
|
- rqdata[0], rqdata[1]);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s",
|
|
- rqdata[0], rqdata[1],
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ user_access.channel = channel;
|
|
+ user_access.user_id = user_id;
|
|
+ ccode = _ipmi_get_user_access(intf, &user_access);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Get User Access (channel %d id %d)",
|
|
+ channel, user_id);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
|
|
-
|
|
- memset(&set_access, 0, sizeof(set_access));
|
|
- set_access.change_bits = 1;
|
|
- set_access.callin_callback = user_access.callin_callback;
|
|
- set_access.link_auth = user_access.link_auth;
|
|
- set_access.ipmi_messaging = user_access.ipmi_messaging;
|
|
- set_access.channel = channel;
|
|
- set_access.user_id = userid;
|
|
- set_access.privilege_limit = user_access.privilege_limit;
|
|
- set_access.session_limit = 0;
|
|
-
|
|
- for (i = 2; i < argc; i ++)
|
|
- {
|
|
+ for (i = 3; i < argc; i ++) {
|
|
if (strncmp(argv[i], "callin=", 7) == 0) {
|
|
- set_access.callin_callback = !(strncmp (argv[i]+7, "off", 3));
|
|
- }
|
|
- else if (strncmp(argv[i], "link=", 5) == 0) {
|
|
- set_access.link_auth = strncmp (argv[i]+5, "off", 3);
|
|
- }
|
|
- else if (strncmp(argv[i], "ipmi=", 5) == 0) {
|
|
- set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3);
|
|
- }
|
|
- else if (strncmp(argv[i], "privilege=", 10) == 0) {
|
|
- if (str2uchar(argv[i]+10, &privilege_limit) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[i]+10);
|
|
- return (-1);
|
|
+ if (strncmp(argv[i] + 7, "off", 3) == 0) {
|
|
+ user_access.callin_callback = 1;
|
|
+ } else {
|
|
+ user_access.callin_callback = 0;
|
|
}
|
|
- set_access.privilege_limit = privilege_limit;
|
|
- }
|
|
- else {
|
|
- printf ("Invalid option: %s\n", argv [i]);
|
|
- return -1;
|
|
- }
|
|
- }
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = IPMI_SET_USER_ACCESS;
|
|
- req.msg.data = (uint8_t *) &set_access;
|
|
- req.msg.data_len = 4;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set User Access (channel %d id %d)",
|
|
- set_access.channel, set_access.user_id);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set User Access (channel %d id %d) failed: %s",
|
|
- set_access.channel, set_access.user_id,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-static const char *
|
|
-iana_string(uint32_t iana)
|
|
-{
|
|
- static char s[10];
|
|
-
|
|
- if (iana)
|
|
- {
|
|
- sprintf(s, "%06x", iana);
|
|
- return s;
|
|
- }
|
|
- else
|
|
- return "N/A";
|
|
-}
|
|
-
|
|
-
|
|
-static int
|
|
-ipmi_get_channel_cipher_suites(struct ipmi_intf * intf,
|
|
- const char * payload_type,
|
|
- uint8_t channel)
|
|
-{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- uint8_t oem_record;
|
|
- uint8_t rqdata[3];
|
|
- uint32_t iana;
|
|
- uint8_t auth_alg, integrity_alg, crypt_alg;
|
|
- uint8_t cipher_suite_id;
|
|
- uint8_t list_index = 0;
|
|
- uint8_t cipher_suite_data[1024]; // 0x40 sets * 16 bytes per set
|
|
- uint16_t offset = 0;
|
|
- uint16_t cipher_suite_data_length = 0; // how much was returned, total
|
|
-
|
|
- memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; // 0x06
|
|
- req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; // 0x54
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 3;
|
|
-
|
|
- rqdata[0] = channel;
|
|
- rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1);
|
|
- rqdata[2] = 0x80; // Always ask for cipher suite format
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
-
|
|
-
|
|
- // Grab the returned channel number once. We assume it's the same
|
|
- // in future calls.
|
|
- if (rsp->data_len >= 1)
|
|
- channel = rsp->data[0];
|
|
-
|
|
- while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F))
|
|
- {
|
|
- //
|
|
- // We got back cipher suite data -- store it.
|
|
- //printf("copying data to offset %d\n", offset);
|
|
- //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
|
|
- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
|
|
- offset += rsp->data_len - 1;
|
|
-
|
|
- //
|
|
- // Increment our list for the next call
|
|
- //
|
|
- ++list_index;
|
|
- rqdata[2] = (rqdata[2] & 0x80) + list_index;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Copy last chunk */
|
|
- if(rsp->data_len > 1)
|
|
- {
|
|
- //
|
|
- // We got back cipher suite data -- store it.
|
|
- //printf("copying data to offset %d\n", offset);
|
|
- //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
|
|
- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
|
|
- offset += rsp->data_len - 1;
|
|
- }
|
|
-
|
|
- //
|
|
- // We can chomp on all our data now.
|
|
- //
|
|
- cipher_suite_data_length = offset;
|
|
- offset = 0;
|
|
-
|
|
- if (! csv_output)
|
|
- printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
|
|
-
|
|
- while (offset < cipher_suite_data_length)
|
|
- {
|
|
- if (cipher_suite_data[offset++] == 0xC0)
|
|
- {
|
|
- oem_record = 0; // standard type
|
|
- iana = 0;
|
|
-
|
|
- // Verify that we have at least a full record left
|
|
- if ((cipher_suite_data_length - offset) < 4) // id + 3 algs
|
|
- {
|
|
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
|
|
- return -1;
|
|
+ } else if (strncmp(argv[i], "link=", 5) == 0) {
|
|
+ if (strncmp(argv[i] + 5, "off", 3) == 0) {
|
|
+ user_access.link_auth = 0;
|
|
+ } else {
|
|
+ user_access.link_auth = 1;
|
|
}
|
|
-
|
|
- cipher_suite_id = cipher_suite_data[offset++];
|
|
-
|
|
- }
|
|
- else if (cipher_suite_data[offset++] == 0xC1)
|
|
- {
|
|
- oem_record = 1; // OEM record type
|
|
-
|
|
- // Verify that we have at least a full record left
|
|
- if ((cipher_suite_data_length - offset) < 4) // id + iana + 3 algs
|
|
- {
|
|
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
|
|
- return -1;
|
|
+ } else if (strncmp(argv[i], "ipmi=", 5) == 0) {
|
|
+ if (strncmp(argv[i] + 5, "off", 3) == 0) {
|
|
+ user_access.ipmi_messaging = 0;
|
|
+ } else {
|
|
+ user_access.ipmi_messaging = 1;
|
|
}
|
|
-
|
|
- cipher_suite_id = cipher_suite_data[offset++];
|
|
-
|
|
- //
|
|
- // Grab the IANA
|
|
- //
|
|
- iana =
|
|
- cipher_suite_data[offset] |
|
|
- (cipher_suite_data[offset + 1] << 8) |
|
|
- (cipher_suite_data[offset + 2] << 16);
|
|
- offset += 3;
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_ERR, "Bad start of record byte in cipher suite data");
|
|
- return -1;
|
|
- }
|
|
-
|
|
- //
|
|
- // Grab the algorithms for this cipher suite. I guess we can't be
|
|
- // sure of what order they'll come in. Also, I suppose we default
|
|
- // to the NONE algorithm if one were absent. This part of the spec is
|
|
- // poorly written -- I have read the errata document. For now, I'm only
|
|
- // allowing one algorithm per type (auth, integrity, crypt) because I
|
|
- // don't I understand how it could be otherwise.
|
|
- //
|
|
- auth_alg = IPMI_AUTH_RAKP_NONE;
|
|
- integrity_alg = IPMI_INTEGRITY_NONE;
|
|
- crypt_alg = IPMI_CRYPT_NONE;
|
|
-
|
|
- while (((cipher_suite_data[offset] & 0xC0) != 0xC0) &&
|
|
- ((cipher_suite_data_length - offset) > 0))
|
|
- {
|
|
- switch (cipher_suite_data[offset] & 0xC0)
|
|
- {
|
|
- case 0x00:
|
|
- // Authentication algorithm specifier
|
|
- auth_alg = cipher_suite_data[offset++] & 0x3F;
|
|
- break;
|
|
- case 0x40:
|
|
- // Interity algorithm specifier
|
|
- integrity_alg = cipher_suite_data[offset++] & 0x3F;
|
|
- break;
|
|
- case 0x80:
|
|
- // Confidentiality algorithm specifier
|
|
- crypt_alg = cipher_suite_data[offset++] & 0x3F;
|
|
- break;
|
|
+ } else if (strncmp(argv[i], "privilege=", 10) == 0) {
|
|
+ if (str2uchar(argv[i] + 10, &priv) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Numeric value expected, but '%s' given.",
|
|
+ argv[i] + 10);
|
|
+ return (-1);
|
|
}
|
|
+ user_access.privilege_limit = priv;
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Invalid option: %s\n", argv[i]);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
-
|
|
- //
|
|
- // We have everything we need to spit out a cipher suite record
|
|
- //
|
|
- printf((csv_output? "%d,%s,%s,%s,%s\n" :
|
|
- "%-4d %-7s %-15s %-15s %-15s\n"),
|
|
- cipher_suite_id,
|
|
- iana_string(iana),
|
|
- val2str(auth_alg, ipmi_auth_algorithms),
|
|
- val2str(integrity_alg, ipmi_integrity_algorithms),
|
|
- val2str(crypt_alg, ipmi_encryption_algorithms));
|
|
}
|
|
-
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-
|
|
-uint8_t
|
|
-ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel)
|
|
-{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- struct get_channel_info_rsp info;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = IPMI_GET_CHANNEL_INFO;
|
|
- req.msg.data = &channel;
|
|
- req.msg.data_len = 1;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Get Channel Info command failed");
|
|
- return 0;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- if (rsp->ccode == 0xcc)
|
|
- return IPMI_CHANNEL_MEDIUM_RESERVED;
|
|
- lprintf(LOG_INFO, "Get Channel Info command failed: %s",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return IPMI_CHANNEL_MEDIUM_RESERVED;
|
|
+ ccode = _ipmi_set_user_access(intf, &user_access, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Set User Access (channel %d id %d)",
|
|
+ channel, user_id);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- memcpy(&info, rsp->data, sizeof(struct get_channel_info_rsp));
|
|
-
|
|
- lprintf(LOG_DEBUG, "Channel type: %s",
|
|
- val2str(info.channel_medium, ipmi_channel_medium_vals));
|
|
-
|
|
- return info.channel_medium;
|
|
-}
|
|
-
|
|
-uint8_t
|
|
-ipmi_current_channel_medium(struct ipmi_intf * intf)
|
|
-{
|
|
- return ipmi_get_channel_medium(intf, 0xE);
|
|
-}
|
|
-
|
|
-void
|
|
-printf_channel_usage()
|
|
-{
|
|
- lprintf(LOG_NOTICE, "Channel Commands: authcap <channel number> <max privilege>");
|
|
- lprintf(LOG_NOTICE, " getaccess <channel number> [user id]");
|
|
- lprintf(LOG_NOTICE, " setaccess <channel number> "
|
|
- "<user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]");
|
|
- lprintf(LOG_NOTICE, " info [channel number]");
|
|
- lprintf(LOG_NOTICE, " getciphers <ipmi | sol> [channel]\n");
|
|
- lprintf(LOG_NOTICE, "Possible privilege levels are:");
|
|
- lprintf(LOG_NOTICE, " 1 Callback level");
|
|
- lprintf(LOG_NOTICE, " 2 User level");
|
|
- lprintf(LOG_NOTICE, " 3 Operator level");
|
|
- lprintf(LOG_NOTICE, " 4 Administrator level");
|
|
- lprintf(LOG_NOTICE, " 5 OEM Proprietary level");
|
|
- lprintf(LOG_NOTICE, " 15 No access");
|
|
+ printf("Set User Access (channel %d id %d) successful.\n",
|
|
+ channel, user_id);
|
|
+ return 0;
|
|
}
|
|
|
|
-
|
|
int
|
|
-ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
+ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
{
|
|
int retval = 0;
|
|
- uint8_t channel, priv = 0;
|
|
-
|
|
- if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0))
|
|
- {
|
|
+ uint8_t channel;
|
|
+ uint8_t priv = 0;
|
|
+ if (argc < 1) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
printf_channel_usage();
|
|
- }
|
|
- else if (strncmp(argv[0], "authcap", 7) == 0)
|
|
- {
|
|
+ return (-1);
|
|
+ } else if (strncmp(argv[0], "help", 4) == 0) {
|
|
+ printf_channel_usage();
|
|
+ return 0;
|
|
+ } else if (strncmp(argv[0], "authcap", 7) == 0) {
|
|
if (argc != 3) {
|
|
printf_channel_usage();
|
|
return (-1);
|
|
- } else {
|
|
- if (str2uchar(argv[1], &channel) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
|
|
- return (-1);
|
|
- }
|
|
- if (str2uchar(argv[2], &priv) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
|
|
- return (-1);
|
|
- }
|
|
- retval = ipmi_get_channel_auth_cap(intf, channel, priv);
|
|
}
|
|
- }
|
|
- else if (strncmp(argv[0], "getaccess", 10) == 0)
|
|
- {
|
|
- if ((argc < 2) || (argc > 3))
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0
|
|
+ || is_ipmi_user_priv_limit(argv[2], &priv) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ retval = ipmi_get_channel_auth_cap(intf, channel, priv);
|
|
+ } else if (strncmp(argv[0], "getaccess", 10) == 0) {
|
|
+ uint8_t user_id = 0;
|
|
+ if ((argc < 2) || (argc > 3)) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
printf_channel_usage();
|
|
- else {
|
|
- uint8_t ch = 0;
|
|
- uint8_t id = 0;
|
|
- if (str2uchar(argv[1], &ch) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
|
|
+ return (-1);
|
|
+ }
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (argc == 3) {
|
|
+ if (is_ipmi_user_id(argv[2], &user_id) != 0) {
|
|
return (-1);
|
|
}
|
|
- if (argc == 3) {
|
|
- if (str2uchar(argv[2], &id) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
|
|
- return (-1);
|
|
- }
|
|
- }
|
|
- retval = ipmi_get_user_access(intf, ch, id);
|
|
}
|
|
- }
|
|
- else if (strncmp(argv[0], "setaccess", 9) == 0)
|
|
- {
|
|
- retval = ipmi_set_user_access(intf, argc-1, &(argv[1]));
|
|
- }
|
|
- else if (strncmp(argv[0], "info", 4) == 0)
|
|
- {
|
|
- if (argc > 2)
|
|
+ retval = ipmi_get_user_access(intf, channel, user_id);
|
|
+ } else if (strncmp(argv[0], "setaccess", 9) == 0) {
|
|
+ return ipmi_set_user_access(intf, (argc - 1), &(argv[1]));
|
|
+ } else if (strncmp(argv[0], "info", 4) == 0) {
|
|
+ channel = 0xE;
|
|
+ if (argc > 2) {
|
|
printf_channel_usage();
|
|
- else {
|
|
- uint8_t ch = 0xe;
|
|
- if (argc == 2) {
|
|
- if (str2uchar(argv[1], &ch) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
|
|
- return (-1);
|
|
- }
|
|
+ return (-1);
|
|
+ }
|
|
+ if (argc == 2) {
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
+ return (-1);
|
|
}
|
|
- retval = ipmi_get_channel_info(intf, ch);
|
|
}
|
|
- }
|
|
-
|
|
- // it channel getciphers <ipmi | sol> [channel]
|
|
- else if (strncmp(argv[0], "getciphers", 10) == 0)
|
|
- {
|
|
- if ((argc < 2) || (argc > 3) ||
|
|
- (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3)))
|
|
+ retval = ipmi_get_channel_info(intf, channel);
|
|
+ } else if (strncmp(argv[0], "getciphers", 10) == 0) {
|
|
+ /* channel getciphers <ipmi|sol> [channel] */
|
|
+ channel = 0xE;
|
|
+ if ((argc < 2) || (argc > 3) ||
|
|
+ (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3))) {
|
|
printf_channel_usage();
|
|
- else
|
|
- {
|
|
- uint8_t ch = 0xe;
|
|
- if (argc == 3) {
|
|
- if (str2uchar(argv[2], &ch) != 0) {
|
|
- lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
|
|
- return (-1);
|
|
- }
|
|
+ return (-1);
|
|
+ }
|
|
+ if (argc == 3) {
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
+ return (-1);
|
|
}
|
|
- retval = ipmi_get_channel_cipher_suites(intf,
|
|
- argv[1], // ipmi | sol
|
|
- ch);
|
|
}
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("Invalid CHANNEL command: %s\n", argv[0]);
|
|
+ retval = ipmi_get_channel_cipher_suites(intf,
|
|
+ argv[1], /* ipmi | sol */
|
|
+ channel);
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Invalid CHANNEL command: %s\n", argv[0]);
|
|
printf_channel_usage();
|
|
retval = -1;
|
|
}
|
|
-
|
|
return retval;
|
|
}
|
|
+
|
|
+/* printf_channel_usage - print-out help. */
|
|
+void
|
|
+printf_channel_usage()
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"Channel Commands: authcap <channel number> <max privilege>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" getaccess <channel number> [user id]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" setaccess <channel number> "
|
|
+"<user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" info [channel number]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" getciphers <ipmi | sol> [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", " <control scope>" },
|
|
+ { 0x00, "disable", "<control scope>"},
|
|
+ { 0xFF, NULL, NULL },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_ctl_domain[] = {
|
|
+ { 0x00, "global", "" },
|
|
+ { 0x02, "per_domain", "<platform|CPU|Memory> (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", "<platform|CPU|Memory> (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", "<platform|CPU|Memory> (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 <platform|CPU|Memory>]" },
|
|
+ { 0x04, "add", "nm policy add policy_id <0-7> [domain <platform|CPU|Memory>] correction auto|soft|hard power <watts>|inlet <temp> trig_lim <param> stats <seconds> enable|disable" },
|
|
+ { 0x05, "remove", "nm policy remove policy_id <0-7> [domain <platform|CPU|Memory>]" },
|
|
+ { 0x06, "limiting", "nm policy limiting [domain <platform|CPU|Memory>]" },
|
|
+ { 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 <platform|CPU|Memory> (default is platform)" },
|
|
+ { 0x02, "min", " min <integer value>" },
|
|
+ { 0x03, "max", "max <integer value>" },
|
|
+ { 0xFF, NULL, NULL },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_alert_opts[] = {
|
|
+ { 0x01, "set", "nm alert set chan <chan> dest <dest> string <string>" },
|
|
+ { 0x02, "get", "nm alert get" },
|
|
+ { 0x03, "clear", "nm alert clear dest <dest>" },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_set_alert_param[] = {
|
|
+ { 0x01, "chan", "chan <channel>" },
|
|
+ { 0x02, "dest", "dest <destination>" },
|
|
+ { 0x03, "string", "string <string>" },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_thresh_cmds[] = {
|
|
+ { 0x01, "set", "nm thresh set [domain <platform|CPU|Memory>] policy_id <policy> thresh_array" },
|
|
+ { 0x02, "get", "nm thresh get [domain <platform|CPU|Memory>] policy_id <policy>" },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_thresh_param[] = {
|
|
+ { 0x01, "domain", "<platform|CPU|Memory> (default is platform)" },
|
|
+ { 0x02, "policy_id", "<0-7>" },
|
|
+ { 0xFF, NULL, NULL },
|
|
+};
|
|
+
|
|
+const struct dcmi_cmd nm_suspend_cmds[] = {
|
|
+ { 0x01, "set", "nm suspend set [domain <platform|CPU|Memory]> policy_id <policy> <start> <stop> <pattern>" },
|
|
+ { 0x02, "get", "nm suspend get [domain <platform|CPU|Memory]> policy_id <policy>" },
|
|
+};
|
|
+
|
|
+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; i<records; i++) {
|
|
/* Record ID is in little endian format */
|
|
record_id = (id_buff[2*i + 1] << 8) + id_buff[2*i];
|
|
@@ -1067,7 +1329,7 @@ ipmi_dcmi_prnt_discvry_snsr(struct ipmi_intf * intf, uint8_t isnsr)
|
|
* @intf: ipmi interface handler
|
|
*/
|
|
static int
|
|
-ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
|
|
+ipmi_dcmi_pwr_rd(struct ipmi_intf * intf, uint8_t sample_time)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
@@ -1079,8 +1341,13 @@ ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
|
|
memset(&t, 0, sizeof(t));
|
|
|
|
msg_data[0] = IPMI_DCMI; /* Group Extension Identification */
|
|
- msg_data[1] = 0x01; /* Mode Power Status */
|
|
- msg_data[2] = 0x00; /* reserved */
|
|
+ if (sample_time) {
|
|
+ msg_data[1] = 0x02; /* Enhanced Power Statistics */
|
|
+ msg_data[2] = sample_time;
|
|
+ } else {
|
|
+ msg_data[1] = 0x01; /* Mode Power Status */
|
|
+ msg_data[2] = 0x00; /* reserved */
|
|
+ }
|
|
msg_data[3] = 0x00; /* reserved */
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
@@ -1110,8 +1377,11 @@ ipmi_dcmi_pwr_rd(struct ipmi_intf * intf)
|
|
val.avg_pwr);
|
|
printf(" IPMI timestamp: %s",
|
|
asctime(&tm_t));
|
|
- printf(" Sampling period: %08d Milliseconds\n",
|
|
- val.sample);
|
|
+ printf(" Sampling period: ");
|
|
+ if (sample_time)
|
|
+ printf("%s \n", val2str2(val.sample,dcmi_sampling_vals));
|
|
+ else
|
|
+ printf("%08u Seconds.\n", val.sample/1000);
|
|
printf(" Power reading state is: ");
|
|
/* mask the rsp->data 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 <command>",
|
|
- -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 <parameter> <value>",
|
|
- -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 <parameter> <value>", -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 <command>", -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 <entityID> <instanceID>");
|
|
- 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 <entityID> <instanceID>");
|
|
- return -1;
|
|
- } else if (argc < 9) {
|
|
- print_strs(dcmi_thermalpolicy_set_parameters_vals,
|
|
- "Set thermalpolicy instance parameters: "
|
|
- "<volatile/nonvolatile/disabled> "
|
|
- "<poweroff/nopoweroff/disabled> "
|
|
- "<sel/nosel/disabled> <templimitByte> <exceptionTime>",
|
|
- -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 <param>] enable|disable policy_id <param> correction <opt> power <watts> limit <param> period <param>
|
|
+ * nm policy remove [domain <param>] policy_id <param>
|
|
+ * nm policy limiting {domain <param>]
|
|
+ */
|
|
+ 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 <minimum> max <maximum>.\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 <parameter> <value>", 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 <parameter> <value>",
|
|
+ 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 <command>", 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 <entityID> <instanceID>");
|
|
+ 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 <entityID> <instanceID>");
|
|
+ return -1;
|
|
+ } else if (argc < 9) {
|
|
+ print_strs(dcmi_thermalpolicy_set_parameters_vals,
|
|
+ "Set thermalpolicy instance parameters: "
|
|
+ "<volatile/nonvolatile/disabled> "
|
|
+ "<poweroff/nopoweroff/disabled> "
|
|
+ "<sel/nosel/disabled> <templimitByte> <exceptionTime>",
|
|
+ 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 <command>",
|
|
+ LOG_ERR, 0);
|
|
+ return -1;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
|
|
- break;
|
|
- default:
|
|
- print_strs(dcmi_thermalpolicy_vals,
|
|
- "thermalpolicy <command>",
|
|
- -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 <command>",
|
|
+ LOG_ERR, 0);
|
|
+ return -1;
|
|
+ }
|
|
+ rc = ipmi_dcmi_parse_power(intf, argc, argv);
|
|
+ break;
|
|
+ /* end power command */
|
|
+ case 0x02:
|
|
+ /* sensor print */
|
|
+ /* Look for each item in the dcmi_discvry_snsr_vals struct
|
|
+ * and if it exists, print the sdr record id(s) for it.
|
|
+ * Use the val from each one as the sensor number.
|
|
+ */
|
|
+ for (i = 0; dcmi_discvry_snsr_vals[i].str != NULL; i++) {
|
|
+ /* get all of the information about this sensor */
|
|
+ rc = ipmi_dcmi_prnt_discvry_snsr(intf,
|
|
+ dcmi_discvry_snsr_vals[i].val);
|
|
+ }
|
|
+ break;
|
|
+ /* end sensor print */
|
|
+ case 0x03:
|
|
+ /* asset tag */
|
|
+ if(ipmi_dcmi_prnt_getassettag(intf) < 0) {
|
|
+ lprintf(LOG_ERR, "Error getting asset tag!");
|
|
+ return -1;
|
|
+ }
|
|
+ break;
|
|
+ /* end asset tag */
|
|
+ case 0x04:
|
|
+ {
|
|
+ /* set asset tag */
|
|
+ if (argc == 1 ) {
|
|
+ print_strs(dcmi_cmd_vals,
|
|
+ "Data Center Management Interface commands",
|
|
+ LOG_ERR, 0);
|
|
+ return -1;
|
|
+ }
|
|
+ if (ipmi_dcmi_prnt_setassettag(intf, (uint8_t *)argv[1]) < 0) {
|
|
+ lprintf(LOG_ERR, "\nError setting asset tag!");
|
|
+ return -1;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ /* end set asset tag */
|
|
+ case 0x05:
|
|
+ /* get management controller identifier string */
|
|
+ if (ipmi_dcmi_prnt_getmngctrlids(intf) < 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error getting management controller identifier string!");
|
|
+ return -1;
|
|
+ }
|
|
+ break;
|
|
+ /* end get management controller identifier string */
|
|
+ case 0x06:
|
|
+ {
|
|
+ /* set management controller identifier string */
|
|
+ if (argc == 1 ) {
|
|
+ print_strs(dcmi_cmd_vals,
|
|
+ "Data Center Management Interface commands",
|
|
+ LOG_ERR, 0);
|
|
+ return -1;
|
|
+ }
|
|
+ if (ipmi_dcmi_prnt_setmngctrlids(intf, (uint8_t *)argv[1]) < 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error setting management controller identifier string!");
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
+ /* end set management controller identifier string */
|
|
+ case 0x07:
|
|
+ /* get/set thermal policy */
|
|
+ rc = ipmi_dcmi_thermalpolicy(intf, argc, argv);
|
|
+ break;
|
|
case 0x08:
|
|
if(ipmi_dcmi_prnt_get_temp_readings(intf) < 0 ) {
|
|
lprintf(LOG_ERR,
|
|
"Error get temperature readings!");
|
|
+ return -1;
|
|
}
|
|
break;
|
|
case 0x09:
|
|
if(ipmi_dcmi_prnt_getconfparam(intf) < 0 ) {
|
|
lprintf(LOG_ERR,
|
|
"Error Get DCMI Configuration Parameters!");
|
|
+ return -1;
|
|
};
|
|
break;
|
|
case 0x0A:
|
|
@@ -2083,7 +3702,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
|
|
if (strncmp(argv[1], "activate_dhcp", 13) != 0) {
|
|
print_strs( dcmi_conf_param_vals,
|
|
"DCMI Configuration Parameters",
|
|
- -1, 0);
|
|
+ LOG_ERR, 0);
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -2091,7 +3710,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
|
|
if (argc != 3 || strncmp(argv[1], "help", 4) == 0) {
|
|
print_strs(dcmi_conf_param_vals,
|
|
"DCMI Configuration Parameters",
|
|
- -1, 0);
|
|
+ LOG_ERR, 0);
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -2132,11 +3751,90 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv)
|
|
/* couldn't detect what the user entered */
|
|
print_strs(dcmi_cmd_vals,
|
|
"Data Center Management Interface commands",
|
|
- -1, 0);
|
|
+ LOG_ERR, 0);
|
|
return -1;
|
|
break;
|
|
}
|
|
printf("\n");
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/* Node Manager main
|
|
+ *
|
|
+ * @intf: nm interface handler
|
|
+ * @argc: argument count
|
|
+ * @argv: argument vector
|
|
+ */
|
|
+int
|
|
+ipmi_nm_main(struct ipmi_intf * intf, int argc, char **argv)
|
|
+{
|
|
+ struct nm_discover disc;
|
|
+
|
|
+ if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
|
|
+ print_strs(nm_cmd_vals,
|
|
+ "Node Manager Interface commands",
|
|
+ LOG_ERR, 0);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ switch (str2val2(argv[0], nm_cmd_vals)) {
|
|
+ /* discover */
|
|
+ case 0x00:
|
|
+ if (_ipmi_nm_discover(intf, &disc))
|
|
+ return -1;
|
|
+ printf(" Node Manager Version %s\n", val2str2(disc.nm_version, nm_version_vals));
|
|
+ printf(" revision %d.%d%d patch version %d\n", disc.major_rev,
|
|
+ disc.minor_rev>>4, disc.minor_rev&0xf, disc.patch_version);
|
|
+ break;
|
|
+ /* capability */
|
|
+ case 0x01:
|
|
+ if (ipmi_nm_getcapabilities(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* policy control enable-disable */
|
|
+ case 0x02:
|
|
+ if (ipmi_nm_control(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* policy */
|
|
+ case 0x03:
|
|
+ if (ipmi_nm_policy(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* Get statistics */
|
|
+ case 0x04:
|
|
+ if (ipmi_nm_get_statistics(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* set power draw range */
|
|
+ case 0x05:
|
|
+ if (ipmi_nm_set_range(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* set/get suspend periods */
|
|
+ case 0x06:
|
|
+ if (ipmi_nm_suspend(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* reset statistics */
|
|
+ case 0x07:
|
|
+ if (ipmi_nm_reset_statistics(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* set/get alert destination */
|
|
+ case 0x08:
|
|
+ if (ipmi_nm_alert(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ /* set/get alert thresholds */
|
|
+ case 0x09:
|
|
+ if (ipmi_nm_thresh(intf, argc, argv))
|
|
+ return -1;
|
|
+ break;
|
|
+ default:
|
|
+ print_strs(nm_cmd_vals, "Node Manager Interface commands", LOG_ERR, 0);
|
|
+ break;
|
|
+ }
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/lib/ipmi_delloem.c b/lib/ipmi_delloem.c
|
|
index 308c513..2214c99 100644
|
|
--- a/lib/ipmi_delloem.c
|
|
+++ b/lib/ipmi_delloem.c
|
|
@@ -273,22 +273,22 @@ ipmi_delloem_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return 0;
|
|
}
|
|
if (0 ==strncmp(argv[current_arg], "lcd\0", 4)) {
|
|
- ipmi_delloem_lcd_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_lcd_main(intf,argc,argv);
|
|
} else if (strncmp(argv[current_arg], "mac\0", 4) == 0) {
|
|
/* mac address*/
|
|
- ipmi_delloem_mac_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_mac_main(intf,argc,argv);
|
|
} else if (strncmp(argv[current_arg], "lan\0", 4) == 0) {
|
|
/* lan address*/
|
|
- ipmi_delloem_lan_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_lan_main(intf,argc,argv);
|
|
} else if (strncmp(argv[current_arg], "setled\0", 7) == 0) {
|
|
/* SetLED support */
|
|
- ipmi_delloem_setled_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_setled_main(intf,argc,argv);
|
|
} else if (strncmp(argv[current_arg], "powermonitor\0", 13) == 0) {
|
|
/*Powermanagement report processing*/
|
|
- ipmi_delloem_powermonitor_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_powermonitor_main(intf,argc,argv);
|
|
} else if (strncmp(argv[current_arg], "vFlash\0", 7) == 0) {
|
|
/* vFlash Support */
|
|
- ipmi_delloem_vFlash_main(intf,argc,argv);
|
|
+ rc = ipmi_delloem_vFlash_main(intf,argc,argv);
|
|
} else {
|
|
usage();
|
|
return -1;
|
|
@@ -453,6 +453,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
} else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
}
|
|
} else if ((strncmp(argv[current_arg], "lcdqualifier\0", 13) == 0)
|
|
@@ -477,6 +479,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
} else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
}
|
|
} else if ((strncmp(argv[current_arg], "errordisplay\0", 13) == 0)
|
|
@@ -499,6 +503,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
} else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
}
|
|
} else if ((strncmp(argv[current_arg], "none\0", 5) == 0)
|
|
@@ -529,6 +535,8 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
} else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
}
|
|
} else if (strncmp(argv[current_arg], "frontpanelaccess\0", 17) == 0) {
|
|
@@ -546,16 +554,22 @@ ipmi_delloem_lcd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
} else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
}
|
|
} else if( (strncmp(argv[current_arg], "help\0", 5) == 0)
|
|
&& (iDRAC_FLAG==0)) {
|
|
ipmi_lcd_usage();
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
return -1;
|
|
}
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid DellOEM command: %s",
|
|
+ argv[current_arg]);
|
|
ipmi_lcd_usage();
|
|
return -1;
|
|
}
|
|
@@ -575,7 +589,6 @@ int
|
|
ipmi_lcd_get_platform_model_name(struct ipmi_intf * intf, char* lcdstring,
|
|
uint8_t max_length, uint8_t field_type)
|
|
{
|
|
- uint8_t data[4];
|
|
int bytes_copied = 0;
|
|
int ii = 0;
|
|
int lcdstring_len = 0;
|
|
@@ -692,7 +705,6 @@ ipmi_idracvalidator_command(struct ipmi_intf * intf)
|
|
static int
|
|
ipmi_lcd_get_configure_command_wh(struct ipmi_intf * intf)
|
|
{
|
|
- uint8_t data[4];
|
|
int rc;
|
|
rc = ipmi_mc_getsysinfo(intf, IPMI_DELL_LCD_CONFIG_SELECTOR, 0, 0,
|
|
sizeof(lcd_mode), &lcd_mode);
|
|
@@ -2047,7 +2059,6 @@ get_nic_selection_mode_12g(struct ipmi_intf* intf,int current_arg,
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
int failover = 0;
|
|
- int nic_selection_mode = 0;
|
|
uint8_t input_length = 0;
|
|
uint8_t msg_data[30];
|
|
|
|
@@ -2210,7 +2221,6 @@ get_nic_selection_mode_12g(struct ipmi_intf* intf,int current_arg,
|
|
static int
|
|
get_nic_selection_mode(int current_arg, char ** argv)
|
|
{
|
|
- int nic_selection_mode = 0;
|
|
if (argv[current_arg] != NULL
|
|
&& strncmp(argv[current_arg], "dedicated\0", 10) == 0) {
|
|
return DEDICATED;
|
|
@@ -3547,7 +3557,6 @@ ipmi_print_power_consmpt_history(struct ipmi_intf * intf, int unit)
|
|
static int
|
|
ipmi_get_power_cap(struct ipmi_intf * intf, IPMI_POWER_CAP * ipmipowercap)
|
|
{
|
|
- uint64_t tempbtuphrconv;
|
|
uint8_t *rdata;
|
|
int rc;
|
|
rc = ipmi_mc_getsysinfo(intf, IPMI_DELL_POWER_CAP, 0, 0,
|
|
diff --git a/lib/ipmi_ekanalyzer.c b/lib/ipmi_ekanalyzer.c
|
|
index 96d3b44..afee48b 100644
|
|
--- a/lib/ipmi_ekanalyzer.c
|
|
+++ b/lib/ipmi_ekanalyzer.c
|
|
@@ -399,7 +399,6 @@ ipmi_ekanalyzer_usage(void)
|
|
static int
|
|
ipmi_ek_get_file_type(char *argument)
|
|
{
|
|
- int index_name=0;
|
|
int filetype = ERROR_STATUS;
|
|
if (strlen(argument) <= MIN_ARGUMENT) {
|
|
return filetype;
|
|
@@ -2773,6 +2772,10 @@ ipmi_ek_display_board_info_area(FILE *input_file, char *board_type,
|
|
ret = fread(additional_data, size_board, 1, input_file);
|
|
if ((ret != 1) || ferror(input_file)) {
|
|
lprintf(LOG_ERR, "Invalid Additional Data!");
|
|
+ if (additional_data != NULL) {
|
|
+ free(additional_data);
|
|
+ additional_data = NULL;
|
|
+ }
|
|
goto out;
|
|
}
|
|
printf("Additional Custom Mfg. Data: %02x",
|
|
diff --git a/lib/ipmi_firewall.c b/lib/ipmi_firewall.c
|
|
index 8bda398..c3f51ad 100644
|
|
--- a/lib/ipmi_firewall.c
|
|
+++ b/lib/ipmi_firewall.c
|
|
@@ -512,7 +512,7 @@ _set_command_enables(struct ipmi_intf * intf,
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
- unsigned char * d, rqdata[19];
|
|
+ unsigned char rqdata[19];
|
|
unsigned int c;
|
|
|
|
if (!p || !lnfn) {
|
|
@@ -568,8 +568,6 @@ _set_command_enables(struct ipmi_intf * intf,
|
|
return -1;
|
|
}
|
|
|
|
- d = rsp->data;
|
|
-
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_APP;
|
|
req.msg.cmd = BMC_SET_COMMAND_ENABLES;
|
|
@@ -591,7 +589,6 @@ _set_command_enables(struct ipmi_intf * intf,
|
|
return -1;
|
|
}
|
|
|
|
- d = rsp->data;
|
|
return 0;
|
|
}
|
|
|
|
@@ -1017,7 +1014,8 @@ ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char
|
|
{
|
|
struct ipmi_function_params p = {0xe, -1, -1, -1, -1};
|
|
struct bmc_fn_support * bmc_fn_support;
|
|
- unsigned int l, n, c, ret;
|
|
+ int ret;
|
|
+ unsigned int l, n, c;
|
|
unsigned char enables[MAX_COMMAND_BYTES];
|
|
|
|
if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
|
|
@@ -1107,10 +1105,15 @@ ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
struct ipmi_function_params p = {0xe, -1, -1, -1, -1};
|
|
struct bmc_fn_support * bmc_fn_support;
|
|
- unsigned int l, n, c, ret;
|
|
+ int ret;
|
|
+ unsigned int l, n, c;
|
|
unsigned char enables[MAX_COMMAND_BYTES];
|
|
|
|
- if (argc > 0 || (argc > 0 && strncmp(argv[0], "help", 4) == 0)) {
|
|
+ if (argc < 1) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
+ printf_firewall_usage();
|
|
+ return (-1);
|
|
+ } else if (argc > 0 && strncmp(argv[0], "help", 4) == 0) {
|
|
printf_firewall_usage();
|
|
return 0;
|
|
}
|
|
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
|
|
index 17afe5f..175f044 100644
|
|
--- a/lib/ipmi_fru.c
|
|
+++ b/lib/ipmi_fru.c
|
|
@@ -958,7 +958,7 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
|
|
}
|
|
}
|
|
|
|
- if (fru_area != NULL) {
|
|
+ if (fru_data != NULL) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
}
|
|
@@ -1082,7 +1082,7 @@ fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru,
|
|
break;
|
|
}
|
|
|
|
- if (fru_area != NULL) {
|
|
+ if (fru_data != NULL) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
}
|
|
@@ -1217,7 +1217,7 @@ fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru,
|
|
break;
|
|
}
|
|
|
|
- if (fru_area != NULL) {
|
|
+ if (fru_data != NULL) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
}
|
|
@@ -1564,8 +1564,6 @@ static void ipmi_fru_oemkontron_get( int argc, char ** argv,uint8_t * fru_data,
|
|
static int badParams=FALSE;
|
|
int start = off;
|
|
int offset = start;
|
|
- int length = len;
|
|
- int i;
|
|
offset += sizeof(struct fru_multirec_oem_header);
|
|
|
|
if(!badParams){
|
|
@@ -2147,7 +2145,6 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length)
|
|
{
|
|
unsigned int entries;
|
|
unsigned int feeds;
|
|
- unsigned int feedcnt;
|
|
unsigned int hwaddr;
|
|
unsigned int i;
|
|
unsigned int id;
|
|
@@ -3700,7 +3697,7 @@ ipmi_fru_upg_ekeying(struct ipmi_intf * intf,
|
|
char * pFileName,
|
|
uint8_t fruId)
|
|
{
|
|
- struct fru_info fruInfo;
|
|
+ struct fru_info fruInfo = {0};
|
|
uint8_t *buf = NULL;
|
|
uint32_t offFruMultiRec = 0;
|
|
uint32_t fruMultiRecSize = 0;
|
|
@@ -4850,8 +4847,6 @@ ipmi_fru_set_field_string_rebuild(struct ipmi_intf * intf, uint8_t fruId,
|
|
struct fru_info fru, struct fru_header header,
|
|
uint8_t f_type, uint8_t f_index, char *f_string)
|
|
{
|
|
- uint8_t msg_data[4];
|
|
- uint8_t checksum;
|
|
int i = 0;
|
|
uint8_t *fru_data_old = NULL;
|
|
uint8_t *fru_data_new = NULL;
|
|
diff --git a/lib/ipmi_fwum.c b/lib/ipmi_fwum.c
|
|
index 68f40d4..d1e3f4f 100644
|
|
--- a/lib/ipmi_fwum.c
|
|
+++ b/lib/ipmi_fwum.c
|
|
@@ -571,7 +571,7 @@ KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output,
|
|
pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
|
|
pGetDevId->fw_rev2 & 0x0f);
|
|
if (((pBoardInfo->iana == IPMI_OEM_KONTRON)
|
|
- && (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002))) {
|
|
+ && (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002))) {
|
|
printf(" SDR %u", pGetDevId->aux_fw_rev[0]);
|
|
}
|
|
printf("\n");
|
|
@@ -837,11 +837,8 @@ KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo)
|
|
do {
|
|
rsp = intf->sendrecv(intf, &req);
|
|
} while (rsp == NULL || rsp->ccode == 0xc0);
|
|
- if (!rsp) {
|
|
- lprintf(LOG_ERR,
|
|
- "Error in FWUM Firmware Finish Firmware Image Download Command.");
|
|
- return (-1);
|
|
- } else if (rsp->ccode != 0) {
|
|
+
|
|
+ if (rsp->ccode != 0) {
|
|
lprintf(LOG_ERR,
|
|
"FWUM Firmware Finish Firmware Image Download returned %x",
|
|
rsp->ccode);
|
|
@@ -861,7 +858,6 @@ KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer,
|
|
unsigned long lastAddress = 0;
|
|
unsigned char sequenceNumber = 0;
|
|
unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
|
|
- unsigned char isLengthValid = 1;
|
|
do {
|
|
writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize;
|
|
/* Reach the end */
|
|
diff --git a/lib/ipmi_hpmfwupg.c b/lib/ipmi_hpmfwupg.c
|
|
index fbb5a62..8ada69b 100644
|
|
--- a/lib/ipmi_hpmfwupg.c
|
|
+++ b/lib/ipmi_hpmfwupg.c
|
|
@@ -998,7 +998,6 @@ HpmfwupgUpgradeStage(struct ipmi_intf *intf,
|
|
unsigned char *pImagePtr;
|
|
unsigned int actionsSize;
|
|
int flagColdReset = FALSE;
|
|
- time_t start,end;
|
|
/* Put pointer after image header */
|
|
pImagePtr = (unsigned char*)
|
|
(pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
@@ -1200,7 +1199,7 @@ HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components,
|
|
} else {
|
|
count = (unsigned short)((pDataTemp+lengthOfBlock) - pData);
|
|
}
|
|
- memcpy(&uploadCmd.req->data, pData, bufLength);
|
|
+ memcpy(&uploadCmd.req->data, pData, count);
|
|
imageOffset = 0x00;
|
|
blockLength = 0x00;
|
|
numTxPkts++;
|
|
@@ -1869,7 +1868,6 @@ HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf,
|
|
struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
int silent)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
@@ -2196,18 +2194,15 @@ HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
lprintf(LOG_DEBUG, "HPM: try to re-open IOL session");
|
|
{
|
|
/* force session re-open */
|
|
- intf->opened = 0;
|
|
- intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE;
|
|
- intf->session->session_id = 0;
|
|
- intf->session->in_seq = 0;
|
|
- intf->session->out_seq = 0;
|
|
- intf->session->active = 0;
|
|
- intf->session->retry = 10;
|
|
+ intf->abort = 1;
|
|
+ intf->close(intf);
|
|
+
|
|
while (intf->open(intf) == HPMFWUPG_ERROR
|
|
&& inaccessTimeoutCounter < inaccessTimeout) {
|
|
inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
|
|
timeoutSec1 = time(NULL);
|
|
}
|
|
+
|
|
/* Fake timeout to retry command */
|
|
fakeRsp.ccode = 0xc3;
|
|
rsp = &fakeRsp;
|
|
diff --git a/lib/ipmi_ime.c b/lib/ipmi_ime.c
|
|
index b520ce5..f8e8c09 100755
|
|
--- a/lib/ipmi_ime.c
|
|
+++ b/lib/ipmi_ime.c
|
|
@@ -431,7 +431,6 @@ static int ImeUpgrade(struct ipmi_intf *intf, char* imageFilename)
|
|
if(currentPercent != shownPercent)
|
|
{
|
|
uint16_t timeElapsedSecond;
|
|
- uint16_t timeRemainingSecond;
|
|
shownPercent = currentPercent;
|
|
printf("Percent: %02i, ", shownPercent);
|
|
time(¤t);
|
|
@@ -965,8 +964,6 @@ static int ImeManualRollback(struct ipmi_intf *intf)
|
|
{
|
|
int rc = IME_SUCCESS;
|
|
tImeStatus imeStatus;
|
|
- time_t start,end,current;
|
|
-
|
|
|
|
rc = ImeUpdateRegisterUpdate(intf, IME_UPDTYPE_MANUAL_ROLLBACK);
|
|
ImeUpdateGetStatus(intf,&imeStatus);
|
|
diff --git a/lib/ipmi_isol.c b/lib/ipmi_isol.c
|
|
index 0338e36..84d7db8 100644
|
|
--- a/lib/ipmi_isol.c
|
|
+++ b/lib/ipmi_isol.c
|
|
@@ -413,7 +413,6 @@ ipmi_isol_deactivate(struct ipmi_intf * intf)
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
uint8_t data[6];
|
|
- struct isol_config_parameters params;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_ISOL;
|
|
diff --git a/lib/ipmi_kontronoem.c b/lib/ipmi_kontronoem.c
|
|
index 48dc684..64860be 100644
|
|
--- a/lib/ipmi_kontronoem.c
|
|
+++ b/lib/ipmi_kontronoem.c
|
|
@@ -105,7 +105,7 @@ ipmi_kontronoem_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
if (argc < 2) {
|
|
lprintf(LOG_ERR, "Not enough parameters given.");
|
|
ipmi_kontron_nextboot_help();
|
|
- rc = (-1);
|
|
+ return (-1);
|
|
}
|
|
rc = ipmi_kontron_nextboot_set(intf, (argc - 1), (argv + 1));
|
|
if (rc == 0) {
|
|
@@ -176,7 +176,6 @@ ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf *intf,
|
|
struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
uint8_t msg_data[2];
|
|
- int i;
|
|
memset(msg_data, 0, sizeof(msg_data));
|
|
/* channel =~ 0x0e => Currently running interface */
|
|
msg_data[0] = channel;
|
|
@@ -347,11 +346,28 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
|
|
/* Position at Board Manufacturer */
|
|
fru_data_offset = (header.offset.board * 8) + 6;
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
/* Position at Board Product Name */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
fru_data_offset_tmp = fru_data_offset;
|
|
/* Position at Serial Number */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
|
|
+ if (fru_area == NULL) {
|
|
+ lprintf(LOG_ERR, "Failed to read FRU Area string.");
|
|
+ free(fru_data);
|
|
+ fru_data = NULL;
|
|
+ free(sn);
|
|
+ sn = NULL;
|
|
+ return (-1);
|
|
+ }
|
|
+
|
|
fru_data_offset++;
|
|
if (strlen(fru_area) != sn_size) {
|
|
printf("The length of the serial number in the FRU Board Area is wrong.\n");
|
|
@@ -359,7 +375,12 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
return(-1);
|
|
+ } else {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
}
|
|
/* Copy the new serial number in the board section saved in memory*/
|
|
memcpy(fru_data + fru_data_offset, sn, sn_size);
|
|
@@ -380,6 +401,8 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
return(-1);
|
|
}
|
|
/* Set the Product Section */
|
|
@@ -390,26 +413,54 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
return(-1);
|
|
}
|
|
/* Position at Product Manufacturer */
|
|
fru_data_offset = (header.offset.product * 8) + 3;
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
/* Position at Product Name */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
/* Position at Product Part */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
/* Position at Product Version */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
|
|
+ if (fru_area != NULL) {
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
+ }
|
|
fru_data_offset_tmp = fru_data_offset;
|
|
/* Position at Serial Number */
|
|
fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
|
|
+ if (fru_area == NULL) {
|
|
+ lprintf(LOG_ERR, "Failed to read FRU Area string.");
|
|
+ free(sn);
|
|
+ sn = NULL;
|
|
+ free(fru_data);
|
|
+ fru_data = NULL;
|
|
+ return (-1);
|
|
+ }
|
|
fru_data_offset ++;
|
|
if (strlen(fru_area) != sn_size) {
|
|
free(sn);
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
printf("The length of the serial number in the FRU Product Area is wrong.\n");
|
|
return(-1);
|
|
}
|
|
@@ -432,12 +483,16 @@ ipmi_kontron_set_serial_number(struct ipmi_intf *intf)
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
return -1;
|
|
}
|
|
free(sn);
|
|
sn = NULL;
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
+ free(fru_area);
|
|
+ fru_area = NULL;
|
|
return(1);
|
|
}
|
|
|
|
diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c
|
|
index 060e753..bb619eb 100644
|
|
--- a/lib/ipmi_lanp.c
|
|
+++ b/lib/ipmi_lanp.c
|
|
@@ -53,9 +53,24 @@
|
|
#include <ipmitool/ipmi_strings.h>
|
|
#include <ipmitool/ipmi_lanp.h>
|
|
#include <ipmitool/ipmi_channel.h>
|
|
+#include <ipmitool/ipmi_user.h>
|
|
|
|
extern int verbose;
|
|
|
|
+static void print_lan_alert_print_usage(void);
|
|
+static void print_lan_alert_set_usage(void);
|
|
+static void print_lan_set_usage(void);
|
|
+static void print_lan_set_access_usage(void);
|
|
+static void print_lan_set_arp_usage(void);
|
|
+static void print_lan_set_auth_usage(void);
|
|
+static void print_lan_set_bakgw_usage(void);
|
|
+static void print_lan_set_cipher_privs_usage(void);
|
|
+static void print_lan_set_defgw_usage(void);
|
|
+static void print_lan_set_ipsrc_usage(void);
|
|
+static void print_lan_set_snmp_usage(void);
|
|
+static void print_lan_set_vlan_usage(void);
|
|
+static void print_lan_usage(void);
|
|
+
|
|
/* is_lan_channel - Check if channel is LAN medium
|
|
*
|
|
* return 1 if channel is LAN
|
|
@@ -530,7 +545,7 @@ lan_set_arp_respond(struct ipmi_intf * intf,
|
|
return set_lan_param(intf, chan, IPMI_LANP_BMC_ARP, &data, 1);
|
|
}
|
|
|
|
-
|
|
+/* TODO - probably move elsewhere */
|
|
static char priv_level_to_char(unsigned char priv_level)
|
|
{
|
|
char ret = 'X';
|
|
@@ -562,7 +577,6 @@ static int
|
|
ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan)
|
|
{
|
|
struct lan_param * p;
|
|
- int rc = 0;
|
|
|
|
if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX) {
|
|
lprintf(LOG_ERR, "Invalid Channel %d", chan);
|
|
@@ -827,10 +841,29 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan)
|
|
else
|
|
printf("%-24s: Not Available\n", p->desc);
|
|
|
|
- return rc;
|
|
+ /* Bad Password Threshold */
|
|
+ p = get_lan_param(intf, chan, IPMI_LANP_BAD_PASS_THRESH);
|
|
+ if (p == NULL)
|
|
+ return -1;
|
|
+ if ((p->data != NULL) && (p->data_len == 6)) {
|
|
+ int tmp;
|
|
+
|
|
+ printf("%-24s: %d\n", p->desc, p->data[1]);
|
|
+ printf("%-24s: %s\n", "Invalid password disable",
|
|
+ p->data[0] & 1 ? "yes" : "no" );
|
|
+ tmp = p->data[2] + (p->data[3] << 8);
|
|
+ printf("%-24s: %d\n", "Attempt Count Reset Int.", tmp * 10);
|
|
+ tmp = p->data[4] + (p->data[5] << 8);
|
|
+ printf("%-24s: %d\n", "User Lockout Interval", tmp * 10);
|
|
+ } else {
|
|
+ printf("%-24s: Not Available\n", p->desc);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/* Configure Authentication Types */
|
|
+/* TODO - probably some code duplication going on ??? */
|
|
static int
|
|
ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * types)
|
|
{
|
|
@@ -898,272 +931,206 @@ ipmi_lan_set_auth(struct ipmi_intf * intf, uint8_t chan, char * level, char * ty
|
|
}
|
|
|
|
static int
|
|
-ipmi_lan_set_password(struct ipmi_intf * intf,
|
|
- uint8_t userid, uint8_t * password)
|
|
+ipmi_lan_set_password(struct ipmi_intf *intf,
|
|
+ uint8_t user_id, const char *password)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t data[18];
|
|
-
|
|
- memset(&data, 0, sizeof(data));
|
|
- data[0] = userid & 0x3f;/* user ID */
|
|
- data[1] = 0x02; /* set password */
|
|
-
|
|
- if (password != NULL)
|
|
- memcpy(data+2, password, __min(strlen((const char *)password), 16));
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x47;
|
|
- req.msg.data = data;
|
|
- req.msg.data_len = 18;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set LAN Password for user %d", userid);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set LAN Password for user %d failed: %s",
|
|
- userid, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ int ccode = 0;
|
|
+ ccode = _ipmi_set_user_password(intf, user_id,
|
|
+ IPMI_PASSWORD_SET_PASSWORD, password, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Unable to Set LAN Password for user %d",
|
|
+ user_id);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
/* adjust our session password
|
|
* or we will no longer be able to communicate with BMC
|
|
*/
|
|
ipmi_intf_session_set_password(intf, (char *)password);
|
|
printf("Password %s for user %d\n",
|
|
- (password == NULL) ? "cleared" : "set", userid);
|
|
+ (password == NULL) ? "cleared" : "set", user_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
+/* ipmi_set_alert_enable - enable/disable PEF alerting for given channel.
|
|
+ *
|
|
+ * @channel - IPMI channel
|
|
+ * @enable - whether to enable/disable PEF alerting for given channel
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error.
|
|
+ */
|
|
static int
|
|
-ipmi_set_alert_enable(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
|
|
+ipmi_set_alert_enable(struct ipmi_intf *intf, uint8_t channel, uint8_t enable)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t rqdata[3];
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
-
|
|
- /* update non-volatile access */
|
|
- rqdata[0] = channel;
|
|
- rqdata[1] = 0x40;
|
|
-
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x41;
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 2;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
-
|
|
- /* SAVE TO NVRAM */
|
|
- memset(rqdata, 0, 3);
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = rsp->data[0];
|
|
- if (enable != 0)
|
|
- rqdata[1] &= ~0x20;
|
|
- else
|
|
- rqdata[1] |= 0x20;
|
|
- rqdata[1] |= 0x40;
|
|
- rqdata[2] = 0;
|
|
-
|
|
- req.msg.cmd = 0x40;
|
|
- req.msg.data_len = 3;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ struct channel_access_t channel_access;
|
|
+ int ccode = 0;
|
|
+ memset(&channel_access, 0, sizeof(channel_access));
|
|
+ channel_access.channel = channel;
|
|
+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Get Channel Access(non-volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- /* SAVE TO CURRENT */
|
|
- rqdata[1] &= 0xc0;
|
|
- rqdata[1] |= 0x80;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
|
|
- return -1;
|
|
+ if (enable != 0) {
|
|
+ channel_access.alerting = 1;
|
|
+ } else {
|
|
+ channel_access.alerting = 0;
|
|
+ }
|
|
+ /* non-volatile */
|
|
+ ccode = _ipmi_set_channel_access(intf, channel_access, 1, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Set Channel Access(non-volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ /* volatile */
|
|
+ ccode = _ipmi_set_channel_access(intf, channel_access, 2, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Set Channel Access(volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
-
|
|
+ printf("PEF alerts for channel %d %s.\n",
|
|
+ channel,
|
|
+ (enable) ? "enabled" : "disabled");
|
|
return 0;
|
|
}
|
|
|
|
+/* ipmi_set_channel_access - enable/disable IPMI messaging for given channel and
|
|
+ * set Privilege Level to Administrator.
|
|
+ *
|
|
+ * @channel - IPMI channel
|
|
+ * @enable - whether to enable/disable IPMI messaging for given channel.
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error
|
|
+ */
|
|
static int
|
|
-ipmi_set_channel_access(struct ipmi_intf * intf, uint8_t channel, uint8_t enable)
|
|
+ipmi_set_channel_access(struct ipmi_intf *intf, uint8_t channel,
|
|
+ uint8_t enable)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t rqdata[3];
|
|
- uint8_t byteEnable;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
-
|
|
- /* RETREIVE VALUE IN NVRAM */
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x41; /* Get Channel Access Command */
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 2;
|
|
-
|
|
- memset(rqdata, 0, 2);
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = 0x40; /* retreive NV */
|
|
+ struct channel_access_t channel_access;
|
|
+ int ccode = 0;
|
|
+ memset(&channel_access, 0, sizeof(channel_access));
|
|
+ channel_access.channel = channel;
|
|
+ /* Get Non-Volatile Channel Access first */
|
|
+ ccode = _ipmi_get_channel_access(intf, &channel_access, 0);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Get Channel Access(non-volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
+ }
|
|
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- } else if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ if (enable != 0) {
|
|
+ channel_access.access_mode = 2;
|
|
} else {
|
|
- byteEnable = *(rsp->data + 0);
|
|
+ channel_access.access_mode = 0;
|
|
+ }
|
|
+ channel_access.privilege_limit = 0x04;
|
|
+ ccode = _ipmi_set_channel_access(intf, channel_access, 1, 1);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Set Channel Access(non-volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
|
|
- /* SAVE TO NVRAM */
|
|
- memset(&req, 0, sizeof(req));
|
|
-
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x40; /* Set Channel Access Command */
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 3;
|
|
-
|
|
- memset(rqdata, 0, 3);
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = 0x40 | (byteEnable & 0x38); /* use previously set values */
|
|
- if (enable != 0)
|
|
- rqdata[1] |= 0x2; /* set always available if enable is set */
|
|
- rqdata[2] = 0x44; /* set channel privilege limit to ADMIN */
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- } else if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ memset(&channel_access, 0, sizeof(channel_access));
|
|
+ channel_access.channel = channel;
|
|
+ /* Get Volatile Channel Access */
|
|
+ ccode = _ipmi_get_channel_access(intf, &channel_access, 1);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Get Channel Access(volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
|
|
- /* RETREIVE VALUE IN NVRAM */
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x41; /* Get Channel Access Command */
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 2;
|
|
-
|
|
- memset(rqdata, 0, 2);
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = 0x80; /* retreive NV */
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Get Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- } else if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ if (enable != 0) {
|
|
+ channel_access.access_mode = 2;
|
|
} else {
|
|
- byteEnable = *(rsp->data + 0);
|
|
- }
|
|
-
|
|
- /* SAVE TO CURRENT */
|
|
- memset(&req, 0, sizeof(req));
|
|
-
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x40; /* Set Channel Access Command */
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 3;
|
|
-
|
|
- memset(rqdata, 0, 3);
|
|
- rqdata[0] = channel & 0xf;
|
|
- rqdata[1] = 0x80 | (byteEnable & 0x38); /* use previously set values */
|
|
- if (enable != 0)
|
|
- rqdata[1] |= 0x2; /* set always available if enable is set */
|
|
- rqdata[2] = 0x84; /* set channel privilege limit to ADMIN */
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set Channel Access for channel %d", channel);
|
|
- return -1;
|
|
- } else if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set Channel Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ channel_access.access_mode = 0;
|
|
+ }
|
|
+ channel_access.privilege_limit = 0x04;
|
|
+ ccode = _ipmi_set_channel_access(intf, channel_access, 2, 2);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Unable to Set Channel Access(volatile) for channel %d",
|
|
+ channel);
|
|
+ return (-1);
|
|
}
|
|
|
|
/* can't send close session if access off so abort instead */
|
|
- if (enable == 0)
|
|
+ if (enable == 0) {
|
|
intf->abort = 1;
|
|
-
|
|
+ }
|
|
+ printf("Set Channel Access for channel %d was successful.\n",
|
|
+ channel);
|
|
return 0;
|
|
}
|
|
|
|
+/* ipmi_set_user_access - set admin access for given user and channel.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel - IPMI channel
|
|
+ * @user_id - IPMI User ID
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error.
|
|
+ */
|
|
static int
|
|
-ipmi_set_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
|
|
+ipmi_set_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t rqdata[4];
|
|
-
|
|
- memset(rqdata, 0, 4);
|
|
- rqdata[0] = 0x90 | (channel & 0xf);
|
|
- rqdata[1] = userid & 0x3f;
|
|
- rqdata[2] = 0x4;
|
|
- rqdata[3] = 0;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = 0x43;
|
|
- req.msg.data = rqdata;
|
|
- req.msg.data_len = 4;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to Set User Access for channel %d", channel);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set User Access for channel %d failed: %s",
|
|
- channel, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ struct user_access_t user_access;
|
|
+ int ccode = 0;
|
|
+ memset(&user_access, 0, sizeof(user_access));
|
|
+ user_access.channel = channel;
|
|
+ user_access.user_id = user_id;
|
|
+ user_access.privilege_limit = 0x04;
|
|
+
|
|
+ ccode = _ipmi_set_user_access(intf, &user_access, 1);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Set User Access for channel %d failed",
|
|
+ channel);
|
|
+ return (-1);
|
|
+ } else {
|
|
+ printf("Set User Access for channel %d was successful.",
|
|
+ channel);
|
|
+ return 0;
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
+/* get_cmdline_macaddr - parse-out MAC address from given string and store it
|
|
+ * into buffer.
|
|
+ *
|
|
+ * @arg: string to be parsed.
|
|
+ * @buf: buffer of 6 to hold parsed MAC address.
|
|
+ *
|
|
+ * returns zero on success, (-1) on error and error message is printed-out.
|
|
+ */
|
|
static int
|
|
-get_cmdline_macaddr(char * arg, uint8_t * buf)
|
|
+get_cmdline_macaddr(char *arg, uint8_t *buf)
|
|
{
|
|
- uint32_t m1, m2, m3, m4, m5, m6;
|
|
+ uint32_t m1 = 0;
|
|
+ uint32_t m2 = 0;
|
|
+ uint32_t m3 = 0;
|
|
+ uint32_t m4 = 0;
|
|
+ uint32_t m5 = 0;
|
|
+ uint32_t m6 = 0;
|
|
if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
&m1, &m2, &m3, &m4, &m5, &m6) != 6) {
|
|
lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
|
|
return -1;
|
|
}
|
|
+ if (m1 > UINT8_MAX || m2 > UINT8_MAX
|
|
+ || m3 > UINT8_MAX || m4 > UINT8_MAX
|
|
+ || m5 > UINT8_MAX || m6 > UINT8_MAX) {
|
|
+ lprintf(LOG_ERR, "Invalid MAC address: %s", arg);
|
|
+ return -1;
|
|
+ }
|
|
buf[0] = (uint8_t)m1;
|
|
buf[1] = (uint8_t)m2;
|
|
buf[2] = (uint8_t)m3;
|
|
@@ -1198,8 +1165,7 @@ get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf)
|
|
* data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers
|
|
* data 9 - maximum priv level for 15th (LSN) cipher.
|
|
*/
|
|
- bzero(buf, 9);
|
|
-
|
|
+ memset(buf, 0, 9);
|
|
for (i = 0; i < 15; ++i)
|
|
{
|
|
unsigned char priv_level = IPMI_SESSION_PRIV_ADMIN;
|
|
@@ -1256,9 +1222,16 @@ static int
|
|
get_cmdline_ipaddr(char * arg, uint8_t * buf)
|
|
{
|
|
uint32_t ip1, ip2, ip3, ip4;
|
|
- if (sscanf(arg, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) {
|
|
+ if (sscanf(arg,
|
|
+ "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
|
|
+ &ip1, &ip2, &ip3, &ip4) != 4) {
|
|
lprintf(LOG_ERR, "Invalid IP address: %s", arg);
|
|
- return -1;
|
|
+ return (-1);
|
|
+ }
|
|
+ if (ip1 > UINT8_MAX || ip2 > UINT8_MAX
|
|
+ || ip3 > UINT8_MAX || ip4 > UINT8_MAX) {
|
|
+ lprintf(LOG_ERR, "Invalid IP address: %s", arg);
|
|
+ return (-1);
|
|
}
|
|
buf[0] = (uint8_t)ip1;
|
|
buf[1] = (uint8_t)ip2;
|
|
@@ -1267,55 +1240,8 @@ get_cmdline_ipaddr(char * arg, uint8_t * buf)
|
|
return 0;
|
|
}
|
|
|
|
-static void ipmi_lan_set_usage(void)
|
|
-{
|
|
- lprintf(LOG_NOTICE, "\nusage: lan set <channel> <command> <parameter>\n");
|
|
- lprintf(LOG_NOTICE, "LAN set command/parameter options:");
|
|
- lprintf(LOG_NOTICE, " ipaddr <x.x.x.x> Set channel IP address");
|
|
- lprintf(LOG_NOTICE, " netmask <x.x.x.x> Set channel IP netmask");
|
|
- lprintf(LOG_NOTICE, " macaddr <x:x:x:x:x:x> Set channel MAC address");
|
|
- lprintf(LOG_NOTICE, " defgw ipaddr <x.x.x.x> Set default gateway IP address");
|
|
- lprintf(LOG_NOTICE, " defgw macaddr <x:x:x:x:x:x> Set default gateway MAC address");
|
|
- lprintf(LOG_NOTICE, " bakgw ipaddr <x.x.x.x> Set backup gateway IP address");
|
|
- lprintf(LOG_NOTICE, " bakgw macaddr <x:x:x:x:x:x> Set backup gateway MAC address");
|
|
- lprintf(LOG_NOTICE, " password <password> Set session password for this channel");
|
|
- lprintf(LOG_NOTICE, " snmp <community string> Set SNMP public community string");
|
|
- lprintf(LOG_NOTICE, " user Enable default user for this channel");
|
|
- lprintf(LOG_NOTICE, " access <on|off> Enable or disable access to this channel");
|
|
- lprintf(LOG_NOTICE, " alert <on|off> Enable or disable PEF alerting for this channel");
|
|
- lprintf(LOG_NOTICE, " arp respond <on|off> Enable or disable BMC ARP responding");
|
|
- lprintf(LOG_NOTICE, " arp generate <on|off> Enable or disable BMC gratuitous ARP generation");
|
|
- lprintf(LOG_NOTICE, " arp interval <seconds> Set gratuitous ARP generation interval");
|
|
- lprintf(LOG_NOTICE, " vlan id <off|<id>> Disable or enable VLAN and set ID (1-4094)");
|
|
- lprintf(LOG_NOTICE, " vlan priority <priority> Set vlan priority (0-7)");
|
|
- lprintf(LOG_NOTICE, " auth <level> <type,..> 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 <source> 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 <channel> vlan id <id>\n"
|
|
- "lan set <channel> vlan id off\n"
|
|
- "lan set <channel> vlan priority <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 <chanel> bad_pass_thresh <thresh_num> <1|0> <reset_interval> <lockout_interval>\n"
|
|
+" <thresh_num> Bad Pasword Threshold number.\n"
|
|
+" <1|0> 1 = generate a Session Audit sensor event.\n"
|
|
+" 0 = do not generate an event.\n"
|
|
+" <reset_interval> Attempt Count Reset Interval. In tens of seconds.\n"
|
|
+" <lockount_interval> 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 <on|off>");
|
|
+ print_lan_set_access_usage();
|
|
return (-1);
|
|
}
|
|
else if (strncmp(argv[2], "help", 4) == 0) {
|
|
- lprintf(LOG_NOTICE, "lan set access <on|off>");
|
|
+ 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 <on|off>");
|
|
+ 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 <channel> arp respond <on|off>\n"
|
|
- "lan set <channel> arp generate <on|off>\n"
|
|
- "lan set <channel> arp interval <seconds>\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 <channel> arp respond <on|off>\n"
|
|
- "lan set <channel> arp generate <on|off>\n"
|
|
- "lan set <channel> arp interval <seconds>\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 <channel> arp generate <on|off>");
|
|
+ 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 <channel> arp generate <on|off>");
|
|
+ print_lan_set_arp_usage();
|
|
return (-1);
|
|
}
|
|
}
|
|
else if (strncmp(argv[2], "respond", 7) == 0) {
|
|
if (argc < 4) {
|
|
- lprintf(LOG_NOTICE, "lan set <channel> arp respond <on|off>");
|
|
+ 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 <channel> arp respond <on|off>");
|
|
+ print_lan_set_arp_usage();
|
|
return (-1);
|
|
}
|
|
}
|
|
else {
|
|
- lprintf(LOG_NOTICE,
|
|
- "lan set <channel> arp respond <on|off>\n"
|
|
- "lan set <channel> arp generate <on|off>\n"
|
|
- "lan set <channel> arp interval <seconds>\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 <channel> auth <level> <type,type,...>\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 <channel> auth <level> <type,type,...>\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 <channel> ipsrc <source>\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 <channel> ipsrc <source>\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 <channel> ipsrc <source>\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 <channel> snmp <community string>");
|
|
+ print_lan_set_snmp_usage();
|
|
return (-1);
|
|
}
|
|
else if (strncmp(argv[2], "help", 4) == 0) {
|
|
- lprintf(LOG_NOTICE, "lan set <channel> snmp <community string>");
|
|
+ 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 <channel> 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 <channel> 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 <channel number> <alert destination> <command> <parameter>\n");
|
|
- lprintf(LOG_NOTICE, " Command/parameter options:\n");
|
|
- lprintf(LOG_NOTICE, " ipaddr <x.x.x.x> Set alert IP address");
|
|
- lprintf(LOG_NOTICE, " macaddr <x:x:x:x:x:x> Set alert MAC address");
|
|
- lprintf(LOG_NOTICE, " gateway <default|backup> Set channel gateway to use for alerts");
|
|
- lprintf(LOG_NOTICE, " ack <on|off> Set Alert Acknowledge on or off");
|
|
- lprintf(LOG_NOTICE, " type <pet|oem1|oem2> Set destination type as PET or OEM");
|
|
- lprintf(LOG_NOTICE, " time <seconds> Set ack timeout or unack retry interval");
|
|
- lprintf(LOG_NOTICE, " retry <number> 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 <channel> <alert> [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 <channel number> <alert destination> <command> <parameter>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Command/parameter options:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" ipaddr <x.x.x.x> Set alert IP address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" macaddr <x:x:x:x:x:x> Set alert MAC address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" gateway <default|backup> Set channel gateway to use for alerts");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" ack <on|off> Set Alert Acknowledge on or off");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" type <pet|oem1|oem2> Set destination type as PET or OEM");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" time <seconds> Set ack timeout or unack retry interval");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" retry <number> Set number of alert retries");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+}
|
|
+
|
|
+static void
|
|
+print_lan_set_usage(void)
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"usage: lan set <channel> <command> <parameter>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"LAN set command/parameter options:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" ipaddr <x.x.x.x> Set channel IP address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" netmask <x.x.x.x> Set channel IP netmask");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" macaddr <x:x:x:x:x:x> Set channel MAC address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" defgw ipaddr <x.x.x.x> Set default gateway IP address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" defgw macaddr <x:x:x:x:x:x> Set default gateway MAC address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" bakgw ipaddr <x.x.x.x> Set backup gateway IP address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" bakgw macaddr <x:x:x:x:x:x> Set backup gateway MAC address");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" password <password> Set session password for this channel");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" snmp <community string> Set SNMP public community string");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" user Enable default user for this channel");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" access <on|off> Enable or disable access to this channel");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" alert <on|off> Enable or disable PEF alerting for this channel");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" arp respond <on|off> Enable or disable BMC ARP responding");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" arp generate <on|off> Enable or disable BMC gratuitous ARP generation");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" arp interval <seconds> Set gratuitous ARP generation interval");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" vlan id <off|<id>> Disable or enable VLAN and set ID (1-4094)");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" vlan priority <priority> Set vlan priority (0-7)");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" auth <level> <type,..> 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 <source> 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 <thresh_num> <1|0> <reset_interval> <lockout_interval>\n"
|
|
+" Set bad password threshold");
|
|
+}
|
|
+
|
|
+static void
|
|
+print_lan_set_access_usage(void)
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set access <on|off>");
|
|
+}
|
|
+
|
|
+static void
|
|
+print_lan_set_arp_usage(void)
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> arp respond <on|off>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> arp generate <on|off>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> arp interval <seconds>");
|
|
+ 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 <channel> auth <level> <type,type,...>");
|
|
+ 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 <channel> 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 <channel> ipsrc <source>");
|
|
+ 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 <channel> snmp <community string>");
|
|
+}
|
|
+
|
|
+static void
|
|
+print_lan_set_vlan_usage(void)
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> vlan id <id>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> vlan id off");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"lan set <channel> vlan priority <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 [<channel number>]");
|
|
- lprintf(LOG_NOTICE, " set <channel number> <command> <parameter>");
|
|
- lprintf(LOG_NOTICE, " alert print <channel number> <alert destination>");
|
|
- lprintf(LOG_NOTICE, " alert set <channel number> <alert destination> <command> <parameter>");
|
|
- lprintf(LOG_NOTICE, " stats get [<channel number>]");
|
|
- lprintf(LOG_NOTICE, " stats clear [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"LAN Commands:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" print [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" set <channel number> <command> <parameter>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" alert print <channel number> <alert destination>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" alert set <channel number> <alert destination> <command> <parameter>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" stats get [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" stats clear [<channel number>]");
|
|
}
|
|
|
|
|
|
@@ -2312,6 +2464,8 @@ ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
|
|
return (-1);
|
|
}
|
|
+ } else {
|
|
+ chan = find_lan_channel(intf, 1);
|
|
}
|
|
if (!is_lan_channel(intf, chan)) {
|
|
lprintf(LOG_ERR, "Invalid channel: %d", chan);
|
|
@@ -2331,6 +2485,8 @@ ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
lprintf(LOG_ERR, "Invalid channel: %s", argv[2]);
|
|
return (-1);
|
|
}
|
|
+ } else {
|
|
+ chan = find_lan_channel(intf, 1);
|
|
}
|
|
if (!is_lan_channel(intf, chan)) {
|
|
lprintf(LOG_ERR, "Invalid channel: %d", chan);
|
|
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
|
|
index 2bbbe4b..cfb05f7 100644
|
|
--- a/lib/ipmi_main.c
|
|
+++ b/lib/ipmi_main.c
|
|
@@ -1,21 +1,21 @@
|
|
/*
|
|
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
|
- *
|
|
+ *
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
- *
|
|
+ *
|
|
* Redistribution of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
- *
|
|
+ *
|
|
* Redistribution in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
- *
|
|
+ *
|
|
* Neither the name of Sun Microsystems, Inc. or the names of
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
- *
|
|
+ *
|
|
* This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
@@ -29,6 +29,7 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _XOPEN_SOURCE 700
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
@@ -263,13 +264,16 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_
|
|
*
|
|
* This insures that the IOL session gets freed
|
|
* for other callers.
|
|
- *
|
|
+ *
|
|
* returns -1
|
|
*/
|
|
void ipmi_catch_sigint()
|
|
{
|
|
if (ipmi_main_intf != NULL) {
|
|
printf("\nSIGN INT: Close Interface %s\n",ipmi_main_intf->desc);
|
|
+ /* reduce retry count to a single retry */
|
|
+ ipmi_main_intf->ssn_params.retry = 1;
|
|
+ /* close interface */
|
|
ipmi_main_intf->close(ipmi_main_intf);
|
|
}
|
|
exit(-1);
|
|
@@ -338,6 +342,18 @@ ipmi_parse_hex(const char *str)
|
|
return out;
|
|
}
|
|
|
|
+static uint8_t
|
|
+ipmi_acquire_ipmb_address(struct ipmi_intf * intf)
|
|
+{
|
|
+ if (intf->picmg_avail) {
|
|
+ return ipmi_picmg_ipmb_address(intf);
|
|
+ } else if (intf->vita_avail) {
|
|
+ return ipmi_vita_ipmb_address(intf);
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
/* ipmi_parse_options - helper function to handle parsing command line options
|
|
*
|
|
* @argc: count of options
|
|
@@ -901,14 +917,22 @@ ipmi_main(int argc, char ** argv,
|
|
}
|
|
}
|
|
/*
|
|
- * Attempt picmg discovery of the actual interface address unless
|
|
+ * Attempt picmg/vita discovery of the actual interface address unless
|
|
* the users specified an address.
|
|
* Address specification always overrides discovery
|
|
*/
|
|
- if (picmg_discover(ipmi_main_intf) && !arg_addr) {
|
|
- lprintf(LOG_DEBUG, "Running PICMG Get Address Info");
|
|
- addr = ipmi_picmg_ipmb_address(ipmi_main_intf);
|
|
- lprintf(LOG_INFO, "Discovered IPMB-0 address 0x%x", addr);
|
|
+ if (picmg_discover(ipmi_main_intf)) {
|
|
+ ipmi_main_intf->picmg_avail = 1;
|
|
+ } else if (vita_discover(ipmi_main_intf)) {
|
|
+ ipmi_main_intf->vita_avail = 1;
|
|
+ }
|
|
+
|
|
+ if (arg_addr) {
|
|
+ addr = arg_addr;
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "Acquire IPMB address");
|
|
+ addr = ipmi_acquire_ipmb_address(ipmi_main_intf);
|
|
+ lprintf(LOG_INFO, "Discovered IPMB address 0x%x", addr);
|
|
}
|
|
|
|
/*
|
|
@@ -916,41 +940,44 @@ ipmi_main(int argc, char ** argv,
|
|
* used for open, Set the discovered IPMB address as my address if the
|
|
* interface supports it.
|
|
*/
|
|
- if (addr != 0 && addr != ipmi_main_intf->my_addr &&
|
|
- ipmi_main_intf->set_my_addr) {
|
|
- /*
|
|
- * Only set the interface address on interfaces which support
|
|
- * it
|
|
- */
|
|
- (void) ipmi_main_intf->set_my_addr(ipmi_main_intf, addr);
|
|
+ if (addr != 0 && addr != ipmi_main_intf->my_addr) {
|
|
+ if (ipmi_main_intf->set_my_addr) {
|
|
+ /*
|
|
+ * Some interfaces need special handling
|
|
+ * when changing local address
|
|
+ */
|
|
+ (void)ipmi_main_intf->set_my_addr(ipmi_main_intf, addr);
|
|
+ }
|
|
+
|
|
+ /* set local address */
|
|
+ ipmi_main_intf->my_addr = addr;
|
|
}
|
|
|
|
+ ipmi_main_intf->target_addr = ipmi_main_intf->my_addr;
|
|
+
|
|
/* If bridging addresses are specified, handle them */
|
|
- if (target_addr > 0) {
|
|
- ipmi_main_intf->target_addr = target_addr;
|
|
- ipmi_main_intf->target_lun = target_lun ;
|
|
- ipmi_main_intf->target_channel = target_channel ;
|
|
- }
|
|
- if (transit_addr > 0) {
|
|
+ if (transit_addr > 0 || target_addr > 0) {
|
|
/* sanity check, transit makes no sense without a target */
|
|
if ((transit_addr != 0 || transit_channel != 0) &&
|
|
- ipmi_main_intf->target_addr == 0) {
|
|
+ target_addr == 0) {
|
|
lprintf(LOG_ERR,
|
|
"Transit address/channel %#x/%#x ignored. "
|
|
"Target address must be specified!",
|
|
transit_addr, transit_channel);
|
|
goto out_free;
|
|
}
|
|
+ ipmi_main_intf->target_addr = target_addr;
|
|
+ ipmi_main_intf->target_channel = target_channel ;
|
|
|
|
ipmi_main_intf->transit_addr = transit_addr;
|
|
ipmi_main_intf->transit_channel = transit_channel;
|
|
- }
|
|
- if (ipmi_main_intf->target_addr > 0) {
|
|
+
|
|
+
|
|
/* must be admin level to do this over lan */
|
|
ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN);
|
|
/* Get the ipmb address of the targeted entity */
|
|
ipmi_main_intf->target_ipmb_addr =
|
|
- ipmi_picmg_ipmb_address(ipmi_main_intf);
|
|
+ ipmi_acquire_ipmb_address(ipmi_main_intf);
|
|
lprintf(LOG_DEBUG, "Specified addressing Target %#x:%#x Transit %#x:%#x",
|
|
ipmi_main_intf->target_addr,
|
|
ipmi_main_intf->target_channel,
|
|
@@ -962,6 +989,9 @@ ipmi_main(int argc, char ** argv,
|
|
}
|
|
}
|
|
|
|
+ /* set target LUN (for RAW command) */
|
|
+ ipmi_main_intf->target_lun = target_lun ;
|
|
+
|
|
lprintf(LOG_DEBUG, "Interface address: my_addr %#x "
|
|
"transit %#x:%#x target %#x:%#x "
|
|
"ipmb_target %#x\n",
|
|
diff --git a/lib/ipmi_mc.c b/lib/ipmi_mc.c
|
|
index 2890c90..a93134e 100644
|
|
--- a/lib/ipmi_mc.c
|
|
+++ b/lib/ipmi_mc.c
|
|
@@ -130,43 +130,41 @@ struct bitfield_data {
|
|
const char * name;
|
|
const char * desc;
|
|
uint32_t mask;
|
|
-};
|
|
-
|
|
-struct bitfield_data mc_enables_bf[] = {
|
|
+} mc_enables_bf[] = {
|
|
{
|
|
- name: "recv_msg_intr",
|
|
- desc: "Receive Message Queue Interrupt",
|
|
- mask: 1<<0,
|
|
+ .name = "recv_msg_intr",
|
|
+ .desc = "Receive Message Queue Interrupt",
|
|
+ .mask = 1<<0,
|
|
},
|
|
{
|
|
- name: "event_msg_intr",
|
|
- desc: "Event Message Buffer Full Interrupt",
|
|
- mask: 1<<1,
|
|
+ .name = "event_msg_intr",
|
|
+ .desc = "Event Message Buffer Full Interrupt",
|
|
+ .mask = 1<<1,
|
|
},
|
|
{
|
|
- name: "event_msg",
|
|
- desc: "Event Message Buffer",
|
|
- mask: 1<<2,
|
|
+ .name = "event_msg",
|
|
+ .desc = "Event Message Buffer",
|
|
+ .mask = 1<<2,
|
|
},
|
|
{
|
|
- name: "system_event_log",
|
|
- desc: "System Event Logging",
|
|
- mask: 1<<3,
|
|
+ .name = "system_event_log",
|
|
+ .desc = "System Event Logging",
|
|
+ .mask = 1<<3,
|
|
},
|
|
{
|
|
- name: "oem0",
|
|
- desc: "OEM 0",
|
|
- mask: 1<<5,
|
|
+ .name = "oem0",
|
|
+ .desc = "OEM 0",
|
|
+ .mask = 1<<5,
|
|
},
|
|
{
|
|
- name: "oem1",
|
|
- desc: "OEM 1",
|
|
- mask: 1<<6,
|
|
+ .name = "oem1",
|
|
+ .desc = "OEM 1",
|
|
+ .mask = 1<<6,
|
|
},
|
|
{
|
|
- name: "oem2",
|
|
- desc: "OEM 2",
|
|
- mask: 1<<7,
|
|
+ .name = "oem2",
|
|
+ .desc = "OEM 2",
|
|
+ .mask = 1<<7,
|
|
},
|
|
{ NULL },
|
|
};
|
|
@@ -217,6 +215,8 @@ printf_sysinfo_usage(int full_help)
|
|
lprintf(LOG_NOTICE, " Valid arguments are:");
|
|
}
|
|
lprintf(LOG_NOTICE,
|
|
+ " system_fw_version System firmware (e.g. BIOS) version");
|
|
+ lprintf(LOG_NOTICE,
|
|
" primary_os_name Primary operating system name");
|
|
lprintf(LOG_NOTICE, " os_name Operating system name");
|
|
lprintf(LOG_NOTICE,
|
|
@@ -914,6 +914,8 @@ sysinfo_param(const char *str, int *maxset)
|
|
else if (!strcmp(str, "delloem_url")) {
|
|
*maxset = 2;
|
|
return IPMI_SYSINFO_DELL_URL;
|
|
+ } else if (!strcmp(str, "system_fw_version")) {
|
|
+ return IPMI_SYSINFO_SYSTEM_FW_VERSION;
|
|
}
|
|
|
|
return (-1);
|
|
diff --git a/lib/ipmi_oem.c b/lib/ipmi_oem.c
|
|
index 89495c0..96db2ea 100644
|
|
--- a/lib/ipmi_oem.c
|
|
+++ b/lib/ipmi_oem.c
|
|
@@ -42,34 +42,34 @@ static int ipmi_oem_ibm(struct ipmi_intf * intf);
|
|
|
|
static struct ipmi_oem_handle ipmi_oem_list[] = {
|
|
{
|
|
- name: "supermicro",
|
|
- desc: "Supermicro IPMIv1.5 BMC with OEM LAN authentication support",
|
|
- setup: ipmi_oem_supermicro,
|
|
+ .name = "supermicro",
|
|
+ .desc = "Supermicro IPMIv1.5 BMC with OEM LAN authentication support",
|
|
+ .setup = ipmi_oem_supermicro,
|
|
},
|
|
{
|
|
- name: "intelwv2",
|
|
- desc: "Intel SE7501WV2 IPMIv1.5 BMC with extra LAN communication support",
|
|
+ .name = "intelwv2",
|
|
+ .desc = "Intel SE7501WV2 IPMIv1.5 BMC with extra LAN communication support",
|
|
},
|
|
{
|
|
- name: "intelplus",
|
|
- desc: "Intel IPMI 2.0 BMC with RMCP+ communication support",
|
|
+ .name = "intelplus",
|
|
+ .desc = "Intel IPMI 2.0 BMC with RMCP+ communication support",
|
|
},
|
|
{
|
|
- name: "icts",
|
|
- desc: "IPMI 2.0 ICTS compliance support",
|
|
+ .name = "icts",
|
|
+ .desc = "IPMI 2.0 ICTS compliance support",
|
|
},
|
|
{
|
|
- name: "ibm",
|
|
- desc: "IBM OEM support",
|
|
- setup: ipmi_oem_ibm,
|
|
+ .name = "ibm",
|
|
+ .desc = "IBM OEM support",
|
|
+ .setup = ipmi_oem_ibm,
|
|
},
|
|
{
|
|
- name: "i82571spt",
|
|
- desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
|
|
+ .name = "i82571spt",
|
|
+ .desc = "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
|
|
},
|
|
{
|
|
- name: "kontron",
|
|
- desc: "Kontron OEM big buffer support"
|
|
+ .name = "kontron",
|
|
+ .desc = "Kontron OEM big buffer support"
|
|
},
|
|
{ 0 }
|
|
};
|
|
diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c
|
|
index 154bf40..1beebf0 100644
|
|
--- a/lib/ipmi_pef.c
|
|
+++ b/lib/ipmi_pef.c
|
|
@@ -674,7 +674,7 @@ ipmi_pef_list_policies(struct ipmi_intf * intf)
|
|
|
|
tbl_size = ipmi_pef_get_policy_table(intf, &ptbl);
|
|
if (!tbl_size) {
|
|
- if (!ptbl) {
|
|
+ if (ptbl != NULL) {
|
|
free(ptbl);
|
|
ptbl = NULL;
|
|
}
|
|
@@ -808,7 +808,7 @@ ipmi_pef_get_info(struct ipmi_intf * intf)
|
|
uint8_t actions, tbl_size;
|
|
|
|
tbl_size = ipmi_pef_get_policy_table(intf, &ptbl);
|
|
- if (!ptbl) {
|
|
+ if (ptbl != NULL) {
|
|
free(ptbl);
|
|
ptbl = NULL;
|
|
}
|
|
diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c
|
|
index 7a66aa5..9dfa0d1 100644
|
|
--- a/lib/ipmi_picmg.c
|
|
+++ b/lib/ipmi_picmg.c
|
|
@@ -1745,18 +1745,8 @@ ipmi_picmg_clk_set(struct ipmi_intf * intf, int argc, char ** argv)
|
|
}
|
|
}
|
|
|
|
-#if 1
|
|
-printf("## ID: %d\n", msg_data[1]);
|
|
-printf("## index: %d\n", msg_data[2]);
|
|
-printf("## setting: 0x%02x\n", msg_data[3]);
|
|
-printf("## family: %d\n", msg_data[4]);
|
|
-printf("## acc: %d\n", msg_data[5]);
|
|
-printf("## freq: %ld\n", freq );
|
|
-printf("## res: %d\n", msg_data[10]);
|
|
-#endif
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
if (!rsp) {
|
|
lprintf(LOG_ERR, "No valid response received.");
|
|
return -1;
|
|
@@ -2335,37 +2325,39 @@ picmg_discover(struct ipmi_intf *intf) {
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
char msg_data;
|
|
+ uint8_t picmg_avail = 0;
|
|
|
|
- if (intf->picmg_avail == 0) {
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
|
|
- msg_data = 0x00;
|
|
- req.msg.data = &msg_data;
|
|
- req.msg.data_len = 1;
|
|
- msg_data = 0;
|
|
-
|
|
- lprintf(LOG_DEBUG, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x",
|
|
- intf->my_addr, intf->transit_addr, intf->target_addr);
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (rsp && !rsp->ccode) {
|
|
- if ( (rsp->data[0] == 0) &&
|
|
- ((rsp->data[1] & 0x0F) == PICMG_ATCA_MAJOR_VERSION
|
|
- || (rsp->data[1] & 0x0F) == PICMG_AMC_MAJOR_VERSION) ) {
|
|
- intf->picmg_avail = 1;
|
|
- lprintf(LOG_DEBUG, "Discovered PICMG Extension %d.%d",
|
|
- (rsp->data[1] & 0x0f), (rsp->data[1] >> 4));
|
|
- }
|
|
- } else {
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_DEBUG,"No Response from Get PICMG Properties");
|
|
- } else {
|
|
- lprintf(LOG_DEBUG,"Error Response %#x from Get PICMG Properities", rsp->ccode);
|
|
- }
|
|
- }
|
|
- }
|
|
- if (intf->picmg_avail == 0) {
|
|
- lprintf(LOG_DEBUG, "No PICMG Extenstion discovered");
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
|
|
+ msg_data = 0x00;
|
|
+ req.msg.data = &msg_data;
|
|
+ req.msg.data_len = 1;
|
|
+ msg_data = 0;
|
|
+
|
|
+ lprintf(LOG_INFO, "Running Get PICMG Properties my_addr %#x, transit %#x, target %#x",
|
|
+ intf->my_addr, intf->transit_addr, intf->target_addr);
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_INFO,"No response from Get PICMG Properties");
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_INFO,"Error response %#x from Get PICMG Properities",
|
|
+ rsp->ccode);
|
|
+ } else if (rsp->data_len < 4) {
|
|
+ lprintf(LOG_INFO,"Invalid Get PICMG Properties response length %d",
|
|
+ rsp->data_len);
|
|
+ } else if (rsp->data[0] != 0) {
|
|
+ lprintf(LOG_INFO,"Invalid Get PICMG Properties group extension %#x",
|
|
+ rsp->data[0]);
|
|
+ } else if ((rsp->data[1] & 0x0F) != PICMG_ATCA_MAJOR_VERSION
|
|
+ && (rsp->data[1] & 0x0F) != PICMG_AMC_MAJOR_VERSION) {
|
|
+ lprintf(LOG_INFO,"Unknown PICMG Extension Version %d.%d",
|
|
+ (rsp->data[1] & 0x0F), (rsp->data[1] >> 4));
|
|
+ } else {
|
|
+ picmg_avail = 1;
|
|
+ lprintf(LOG_INFO, "Discovered PICMG Extension Version %d.%d",
|
|
+ (rsp->data[1] & 0x0f), (rsp->data[1] >> 4));
|
|
}
|
|
- return intf->picmg_avail;
|
|
+
|
|
+ return picmg_avail;
|
|
}
|
|
diff --git a/lib/ipmi_raw.c b/lib/ipmi_raw.c
|
|
index 6959c1f..92c0177 100644
|
|
--- a/lib/ipmi_raw.c
|
|
+++ b/lib/ipmi_raw.c
|
|
@@ -39,13 +39,13 @@
|
|
#include <ipmitool/helper.h>
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/ipmi_raw.h>
|
|
-#include <ipmitool/ipmi_fru.h>
|
|
#include <ipmitool/ipmi_strings.h>
|
|
|
|
#define IPMI_I2C_MASTER_MAX_SIZE 0x40 /* 64 bytes */
|
|
|
|
static int is_valid_param(const char *input_param, uint8_t *uchr_ptr,
|
|
const char *label);
|
|
+int ipmi_spd_print(uint8_t *, int);
|
|
|
|
/* ipmi_master_write_read - Perform I2C write/read transactions
|
|
*
|
|
@@ -130,7 +130,7 @@ ipmi_master_write_read(struct ipmi_intf * intf, uint8_t bus, uint8_t addr,
|
|
return rsp;
|
|
}
|
|
|
|
-#define RAW_SPD_SIZE 256
|
|
+#define RAW_SPD_SIZE 512
|
|
|
|
int
|
|
ipmi_rawspd_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
@@ -337,9 +337,6 @@ ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return -1;
|
|
}
|
|
|
|
- ipmi_intf_session_set_timeout(intf, 15);
|
|
- ipmi_intf_session_set_retry(intf, 1);
|
|
-
|
|
lun = intf->target_lun;
|
|
netfn_tmp = str2val(argv[0], ipmi_netfn_vals);
|
|
if (netfn_tmp == 0xff) {
|
|
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
|
|
index fa7b082..292a7d3 100644
|
|
--- a/lib/ipmi_sdr.c
|
|
+++ b/lib/ipmi_sdr.c
|
|
@@ -3977,7 +3977,7 @@ ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile)
|
|
}
|
|
|
|
while (feof(fp) == 0) {
|
|
- memset(&header, 0, 5);
|
|
+ memset(&header, 0, sizeof(header));
|
|
bc = fread(&header, 1, 5, fp);
|
|
if (bc <= 0)
|
|
break;
|
|
diff --git a/lib/ipmi_sdradd.c b/lib/ipmi_sdradd.c
|
|
index f3bc271..f5bf78a 100644
|
|
--- a/lib/ipmi_sdradd.c
|
|
+++ b/lib/ipmi_sdradd.c
|
|
@@ -512,7 +512,6 @@ int ipmi_parse_range_list(const char *rangeList, unsigned char * pHexList)
|
|
int
|
|
ipmi_sdr_add_from_list(struct ipmi_intf *intf, const char *rangeList)
|
|
{
|
|
- int i;
|
|
int rc = 0;
|
|
int slave_addr;
|
|
int myaddr = intf->target_addr;
|
|
@@ -575,7 +574,6 @@ ipmi_sdr_add_from_list(struct ipmi_intf *intf, const char *rangeList)
|
|
static int
|
|
ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue)
|
|
{
|
|
- struct sdr_get_rs header;
|
|
int rc = 0;
|
|
int fd;
|
|
uint8_t binHdr[5];
|
|
@@ -633,6 +631,7 @@ ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue)
|
|
queue->tail->next = sdrr;
|
|
queue->tail = sdrr;
|
|
}
|
|
+ close(fd);
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c
|
|
index 67e12e3..5df66a7 100644
|
|
--- a/lib/ipmi_sel.c
|
|
+++ b/lib/ipmi_sel.c
|
|
@@ -91,15 +91,22 @@ static int ipmi_sel_oem_readval(char *str)
|
|
* reference to byte positions instead of array indexes which (hopefully)
|
|
* helps make the code easier to read.
|
|
*/
|
|
-static int ipmi_sel_oem_match(uint8_t *evt, struct ipmi_sel_oem_msg_rec rec)
|
|
+static int
|
|
+ipmi_sel_oem_match(uint8_t *evt, const struct ipmi_sel_oem_msg_rec *rec)
|
|
{
|
|
- if (evt[2] == rec.value[SEL_BYTE(3)] &&
|
|
- ((rec.value[SEL_BYTE(4)] < 0) || (evt[3] == rec.value[SEL_BYTE(4)])) &&
|
|
- ((rec.value[SEL_BYTE(5)] < 0) || (evt[4] == rec.value[SEL_BYTE(5)])) &&
|
|
- ((rec.value[SEL_BYTE(6)] < 0) || (evt[5] == rec.value[SEL_BYTE(6)])) &&
|
|
- ((rec.value[SEL_BYTE(7)] < 0) || (evt[6] == rec.value[SEL_BYTE(7)])) &&
|
|
- ((rec.value[SEL_BYTE(11)] < 0) || (evt[10] == rec.value[SEL_BYTE(11)])) &&
|
|
- ((rec.value[SEL_BYTE(12)] < 0) || (evt[11] == rec.value[SEL_BYTE(12)]))) {
|
|
+ if (evt[2] == rec->value[SEL_BYTE(3)]
|
|
+ && ((rec->value[SEL_BYTE(4)] < 0)
|
|
+ || (evt[3] == rec->value[SEL_BYTE(4)]))
|
|
+ && ((rec->value[SEL_BYTE(5)] < 0)
|
|
+ || (evt[4] == rec->value[SEL_BYTE(5)]))
|
|
+ && ((rec->value[SEL_BYTE(6)] < 0)
|
|
+ || (evt[5] == rec->value[SEL_BYTE(6)]))
|
|
+ && ((rec->value[SEL_BYTE(7)] < 0)
|
|
+ || (evt[6] == rec->value[SEL_BYTE(7)]))
|
|
+ && ((rec->value[SEL_BYTE(11)] < 0)
|
|
+ || (evt[10] == rec->value[SEL_BYTE(11)]))
|
|
+ && ((rec->value[SEL_BYTE(12)] < 0)
|
|
+ || (evt[11] == rec->value[SEL_BYTE(12)]))) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
@@ -191,7 +198,7 @@ static void ipmi_sel_oem_message(struct sel_event_record * evt, int verbose)
|
|
int i, j;
|
|
|
|
for (i=0; i < sel_oem_nrecs; i++) {
|
|
- if (ipmi_sel_oem_match((uint8_t *)evt, sel_oem_msg[i])) {
|
|
+ if (ipmi_sel_oem_match((uint8_t *)evt, &sel_oem_msg[i])) {
|
|
printf (csv_output ? ",\"%s\"" : " | %s", sel_oem_msg[i].text);
|
|
for (j=4; j<17; j++) {
|
|
if (sel_oem_msg[i].value[SEL_BYTE(j)] == -3) {
|
|
@@ -531,12 +538,10 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
|
|
struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
char *desc = NULL;
|
|
- char *str;
|
|
int chipset_type = 1;
|
|
int data1;
|
|
int data2;
|
|
int data3;
|
|
- int length;
|
|
int sensor_type;
|
|
uint8_t i = 0;
|
|
uint16_t oem_id = 0;
|
|
@@ -551,12 +556,12 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
|
|
return NULL;
|
|
}
|
|
/* Allocate mem for te Description string */
|
|
- desc = (char *)malloc(SIZE_OF_DESC);
|
|
+ desc = malloc(sizeof(char) * SIZE_OF_DESC);
|
|
if (desc == NULL) {
|
|
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
return NULL;
|
|
}
|
|
- memset(desc,0,SIZE_OF_DESC);
|
|
+ memset(desc, '\0', SIZE_OF_DESC);
|
|
sensor_type = rec->sel_type.standard_type.sensor_type;
|
|
switch (sensor_type) {
|
|
case SENSOR_TYPE_MEMORY:
|
|
@@ -587,17 +592,19 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
|
|
/* check the chipset type */
|
|
oem_id = ipmi_get_oem_id(intf);
|
|
if (oem_id == 0) {
|
|
+ if (desc != NULL) {
|
|
+ free(desc);
|
|
+ desc = NULL;
|
|
+ }
|
|
return NULL;
|
|
}
|
|
- length = sizeof(supermicro_X8);
|
|
- for (i = 0; i < length; i++) {
|
|
+ for (i = 0; supermicro_X8[i] != 0xFFFF; i++) {
|
|
if (oem_id == supermicro_X8[i]) {
|
|
chipset_type = 0;
|
|
break;
|
|
}
|
|
}
|
|
- length = sizeof(supermicro_x9);
|
|
- for (i = 0; i < length; i++) {
|
|
+ for (i = 0; supermicro_x9[i] != 0xFFFF; i++) {
|
|
if (oem_id == supermicro_x9[i]) {
|
|
chipset_type = 2;
|
|
break;
|
|
@@ -616,7 +623,8 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
|
|
(data2 >> 4) + 0x40 + (data3 & 0x3) * 3,
|
|
(data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
|
|
} else {
|
|
- snprintf(desc, SIZE_OF_DESC, "");
|
|
+ /* No description. */
|
|
+ desc[0] = '\0';
|
|
}
|
|
break;
|
|
case SENSOR_TYPE_SUPERMICRO_OEM:
|
|
@@ -650,17 +658,13 @@ char * get_dell_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
|
|
|
unsigned char count;
|
|
unsigned char node;
|
|
- unsigned char num;
|
|
unsigned char dimmNum;
|
|
unsigned char dimmsPerNode;
|
|
char dimmStr[MAX_DIMM_STR];
|
|
- char cardStr[MAX_CARD_STR];
|
|
- char numStr[MAX_CARDNO_STR];
|
|
char tmpdesc[SIZE_OF_DESC];
|
|
char* str;
|
|
unsigned char incr = 0;
|
|
unsigned char i=0,j = 0;
|
|
- unsigned char postCode;
|
|
struct ipmi_rs *rsp;
|
|
struct ipmi_rq req;
|
|
char tmpData;
|
|
@@ -1234,6 +1238,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
sfx = ipmi_get_oem_desc(intf, rec);
|
|
break;
|
|
/* add your oem sensor assignation here */
|
|
+ default:
|
|
+ break;
|
|
}
|
|
if( evt == NULL ){
|
|
lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description",
|
|
@@ -1247,6 +1253,8 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
code = rec->sel_type.standard_type.sensor_type;
|
|
sfx = ipmi_get_oem_desc(intf, rec);
|
|
break;
|
|
+ default:
|
|
+ break;
|
|
}
|
|
}
|
|
if( evt == NULL ){
|
|
@@ -1915,6 +1923,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
|
|
case IPMI_OEM_SUPERMICRO_47488:
|
|
print_sensor = 0;
|
|
break;
|
|
+ default:
|
|
+ break;
|
|
}
|
|
/*
|
|
* Sensor-Specific Discrete
|
|
@@ -2832,7 +2842,6 @@ ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
|
for (; argc != 0; argc--)
|
|
{
|
|
- id = (uint16_t) strtoul(argv[argc-1], NULL, 0);
|
|
if (str2ushort(argv[argc-1], &id) != 0) {
|
|
lprintf(LOG_ERR, "Given SEL ID '%s' is invalid.",
|
|
argv[argc-1]);
|
|
@@ -2869,25 +2878,27 @@ ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv)
|
|
static int
|
|
ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
- uint16_t id;
|
|
- int i, oldv;
|
|
- struct sel_event_record evt;
|
|
- struct sdr_record_list * sdr;
|
|
struct entity_id entity;
|
|
- struct sdr_record_list * list, * entry;
|
|
+ struct sdr_record_list *entry;
|
|
+ struct sdr_record_list *list;
|
|
+ struct sdr_record_list *sdr;
|
|
+ struct sel_event_record evt;
|
|
+ int i;
|
|
+ int oldv;
|
|
int rc = 0;
|
|
+ uint16_t id;
|
|
|
|
if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
|
|
lprintf(LOG_ERR, "usage: sel get <id>...<id>");
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
|
|
if (ipmi_sel_reserve(intf) == 0) {
|
|
lprintf(LOG_ERR, "Unable to reserve SEL");
|
|
- return -1;
|
|
+ return (-1);
|
|
}
|
|
|
|
- for (i=0; i<argc; i++) {
|
|
+ for (i = 0; i < argc; i++) {
|
|
if (str2ushort(argv[i], &id) != 0) {
|
|
lprintf(LOG_ERR, "Given SEL ID '%s' is invalid.",
|
|
argv[i]);
|
|
@@ -2903,23 +2914,28 @@ ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv)
|
|
rc = (-1);
|
|
continue;
|
|
}
|
|
- if (evt.sel_type.standard_type.sensor_num == 0 && evt.sel_type.standard_type.sensor_type == 0 && evt.record_type == 0) {
|
|
+ if (evt.sel_type.standard_type.sensor_num == 0
|
|
+ && evt.sel_type.standard_type.sensor_type == 0
|
|
+ && evt.record_type == 0) {
|
|
lprintf(LOG_WARN, "SEL Entry 0x%x not found", id);
|
|
- rc = -1;
|
|
+ rc = (-1);
|
|
continue;
|
|
}
|
|
|
|
/* lookup SDR entry based on sensor number and type */
|
|
ipmi_sel_print_extended_entry_verbose(intf, &evt);
|
|
|
|
- sdr = ipmi_sdr_find_sdr_bynumtype(intf, evt.sel_type.standard_type.gen_id, evt.sel_type.standard_type.sensor_num, evt.sel_type.standard_type.sensor_type);
|
|
+ sdr = ipmi_sdr_find_sdr_bynumtype(intf,
|
|
+ evt.sel_type.standard_type.gen_id,
|
|
+ evt.sel_type.standard_type.sensor_num,
|
|
+ evt.sel_type.standard_type.sensor_type);
|
|
if (sdr == NULL) {
|
|
continue;
|
|
}
|
|
|
|
/* print SDR entry */
|
|
oldv = verbose;
|
|
- verbose = verbose ? : 1;
|
|
+ verbose = verbose ? verbose : 1;
|
|
switch (sdr->type) {
|
|
case SDR_RECORD_TYPE_FULL_SENSOR:
|
|
case SDR_RECORD_TYPE_COMPACT_SENSOR:
|
|
@@ -2947,8 +2963,9 @@ ipmi_sel_show_entry(struct ipmi_intf * intf, int argc, char ** argv)
|
|
ipmi_fru_print(intf, entry->record.fruloc);
|
|
}
|
|
|
|
- if ((argc > 1) && (i<(argc-1)))
|
|
+ if ((argc > 1) && (i < (argc - 1))) {
|
|
printf("----------------------\n\n");
|
|
+ }
|
|
}
|
|
|
|
return rc;
|
|
diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c
|
|
index c138c67..063dfb0 100644
|
|
--- a/lib/ipmi_sensor.c
|
|
+++ b/lib/ipmi_sensor.c
|
|
@@ -1,21 +1,21 @@
|
|
/*
|
|
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
|
- *
|
|
+ *
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
- *
|
|
+ *
|
|
* Redistribution of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
- *
|
|
+ *
|
|
* Redistribution in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
- *
|
|
+ *
|
|
* Neither the name of Sun Microsystems, Inc. or the names of
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
- *
|
|
+ *
|
|
* This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
@@ -52,8 +52,8 @@ void print_sensor_thresh_usage();
|
|
// static
|
|
int
|
|
ipmi_sensor_get_sensor_reading_factors(
|
|
- struct ipmi_intf * intf,
|
|
- struct sdr_record_full_sensor * sensor,
|
|
+ struct ipmi_intf * intf,
|
|
+ struct sdr_record_full_sensor * sensor,
|
|
uint8_t reading)
|
|
{
|
|
struct ipmi_rq req;
|
|
@@ -88,9 +88,9 @@ ipmi_sensor_get_sensor_reading_factors(
|
|
return -1;
|
|
} else {
|
|
/* Update SDR copy with updated Reading Factors for this reading */
|
|
- /* Note:
|
|
- * The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
|
|
- * therefore we can use raw copy operation here.
|
|
+ /* Note:
|
|
+ * The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
|
|
+ * therefore we can use raw copy operation here.
|
|
* Note: rsp->data[0] would point to the next valid entry in the sampling table
|
|
*/
|
|
// BUGBUG: uses 'hardcoded' length information from SDR Definition
|
|
@@ -160,7 +160,6 @@ ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf,
|
|
struct sdr_record_common_sensor *sensor,
|
|
uint8_t sdr_record_type)
|
|
{
|
|
- const char *id;
|
|
struct sensor_reading *sr;
|
|
|
|
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
|
|
@@ -892,8 +891,20 @@ ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv)
|
|
/* need to set verbose level to 1 */
|
|
v = verbose;
|
|
verbose = 1;
|
|
- if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
|
|
- rc = (-1);
|
|
+ switch (sdr->type) {
|
|
+ case SDR_RECORD_TYPE_FULL_SENSOR:
|
|
+ case SDR_RECORD_TYPE_COMPACT_SENSOR:
|
|
+ if (ipmi_sensor_print_fc(intf,
|
|
+ (struct sdr_record_common_sensor *) sdr->record.common,
|
|
+ sdr->type)) {
|
|
+ rc = -1;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
|
|
+ rc = (-1);
|
|
+ }
|
|
+ break;
|
|
}
|
|
verbose = v;
|
|
sdr = NULL;
|
|
diff --git a/lib/ipmi_sol.c b/lib/ipmi_sol.c
|
|
index cf58b44..5415ea7 100644
|
|
--- a/lib/ipmi_sol.c
|
|
+++ b/lib/ipmi_sol.c
|
|
@@ -544,8 +544,8 @@ ipmi_get_sol_info(
|
|
case 0x80:
|
|
if( intf->session != NULL ) {
|
|
lprintf(LOG_ERR, "Info: SOL parameter '%s' not supported - defaulting to %d",
|
|
- val2str(data[1], sol_parameter_vals), intf->session->port);
|
|
- params->payload_port = intf->session->port;
|
|
+ val2str(data[1], sol_parameter_vals), intf->ssn_params.port);
|
|
+ params->payload_port = intf->ssn_params.port;
|
|
} else {
|
|
lprintf(LOG_ERR,
|
|
"Info: SOL parameter '%s' not supported - can't determine which "
|
|
@@ -1235,14 +1235,14 @@ printSolEscapeSequences(struct ipmi_intf * intf)
|
|
%c? - this message\n\
|
|
%c%c - send the escape character by typing it twice\n\
|
|
(Note that escapes are only recognized immediately after newline.)\n",
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char);
|
|
}
|
|
|
|
|
|
@@ -1300,7 +1300,7 @@ ipmi_sol_deactivate(struct ipmi_intf * intf, int instance)
|
|
req.msg.data_len = 6;
|
|
req.msg.data = data;
|
|
|
|
- bzero(data, sizeof(data));
|
|
+ memset(data, 0, sizeof(data));
|
|
data[0] = IPMI_PAYLOAD_TYPE_SOL; /* payload type */
|
|
data[1] = instance; /* payload instance. */
|
|
|
|
@@ -1379,25 +1379,25 @@ processSolUserInput(
|
|
switch (ch) {
|
|
case '.':
|
|
printf("%c. [terminated ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
retval = 1;
|
|
break;
|
|
|
|
case 'Z' - 64:
|
|
printf("%c^Z [suspend ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
suspendSelf(1); /* Restore tty back to raw */
|
|
continue;
|
|
|
|
case 'X' - 64:
|
|
printf("%c^Z [suspend ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
suspendSelf(0); /* Don't restore to raw mode */
|
|
continue;
|
|
|
|
case 'B':
|
|
printf("%cB [send break]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
sendBreak(intf);
|
|
continue;
|
|
|
|
@@ -1406,16 +1406,16 @@ processSolUserInput(
|
|
continue;
|
|
|
|
default:
|
|
- if (ch != intf->session->sol_escape_char)
|
|
+ if (ch != intf->ssn_params.sol_escape_char)
|
|
v2_payload.payload.sol_packet.data[length++] =
|
|
- intf->session->sol_escape_char;
|
|
+ intf->ssn_params.sol_escape_char;
|
|
v2_payload.payload.sol_packet.data[length++] = ch;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
- if (last_was_cr && (ch == intf->session->sol_escape_char)) {
|
|
+ if (last_was_cr && (ch == intf->ssn_params.sol_escape_char)) {
|
|
escape_pending = 1;
|
|
continue;
|
|
}
|
|
@@ -1441,7 +1441,7 @@ processSolUserInput(
|
|
struct ipmi_rs * rsp = NULL;
|
|
int try = 0;
|
|
|
|
- while (try < intf->session->retry) {
|
|
+ while (try < intf->ssn_params.retry) {
|
|
|
|
v2_payload.payload.sol_packet.character_count = length;
|
|
|
|
@@ -1827,12 +1827,12 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
|
|
|
|
/* NOTE: the spec does allow for SOL traffic to be sent on
|
|
* a different port. we do not yet support that feature. */
|
|
- if (intf->session->sol_data.port != intf->session->port)
|
|
+ if (intf->session->sol_data.port != intf->ssn_params.port)
|
|
{
|
|
/* try byteswapping port in case BMC sent it incorrectly */
|
|
uint16_t portswap = BSWAP_16(intf->session->sol_data.port);
|
|
|
|
- if (portswap == intf->session->port) {
|
|
+ if (portswap == intf->ssn_params.port) {
|
|
intf->session->sol_data.port = portswap;
|
|
}
|
|
else {
|
|
@@ -1842,7 +1842,7 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
|
|
}
|
|
|
|
printf("[SOL Session operational. Use %c? for help]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
|
|
if(looptest == 1)
|
|
{
|
|
@@ -1942,10 +1942,6 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
- if (argc == 1 || argc > 4) {
|
|
- print_sol_usage();
|
|
- return -1;
|
|
- }
|
|
if (argc >= 3) {
|
|
if (is_ipmi_channel_num(argv[2], &channel) != 0) {
|
|
return (-1);
|
|
diff --git a/lib/ipmi_strings.c b/lib/ipmi_strings.c
|
|
index 277b82f..4a1ff46 100644
|
|
--- a/lib/ipmi_strings.c
|
|
+++ b/lib/ipmi_strings.c
|
|
@@ -68,6 +68,9 @@ const struct valstr ipmi_oem_info[] = {
|
|
{ IPMI_OEM_BULL, "Bull Company" },
|
|
{ IPMI_OEM_PPS, "Pigeon Point Systems" },
|
|
{ IPMI_OEM_BROADCOM, "Broadcom Corporation" },
|
|
+ { IPMI_OEM_ERICSSON, "Ericsson AB"},
|
|
+ { IPMI_OEM_QUANTA, "Quanta" },
|
|
+ { IPMI_OEM_ADVANTECH, "Advantech" },
|
|
{ 0xffff , NULL },
|
|
};
|
|
|
|
@@ -115,6 +118,90 @@ const struct oemvalstr ipmi_oem_product_info[] = {
|
|
{ IPMI_OEM_KONTRON,5303, "AT8901" },
|
|
/* Broadcom */
|
|
{ IPMI_OEM_BROADCOM, 5725, "BCM5725" },
|
|
+ /* Ericsson */
|
|
+ { IPMI_OEM_ERICSSON, 0x0054, "Phantom" },
|
|
+ /* Advantech */
|
|
+ /* ATCA Blades */
|
|
+ { IPMI_OEM_ADVANTECH, 0x3393, "MIC-3393" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3395, "MIC-3395" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3396, "MIC-3396" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5302, "MIC-5302" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5304, "MIC-5304" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5320, "MIC-5320" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5321, "MIC-5321" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5322, "MIC-5322" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5332, "MIC-5332" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5333, "MIC-5333" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5342, "MIC-5342" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5343, "MIC-5343" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5344, "MIC-5344" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5345, "MIC-5345" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5201, "MIC-5201 Dual 10GE AMC"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x5203, "MIC-5203 Quad GbE AMC"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x5212, "MIC-5212 Dual 10GE AMC"},
|
|
+ /* AdvancedMC */
|
|
+ { IPMI_OEM_ADVANTECH, 0x5401, "MIC-5401" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5601, "MIC-5601" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5602, "MIC-5602" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5604, "MIC-5604" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5603, "MIC-5603" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6311, "MIC-6311" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6313, "MIC-6313" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x8301, "MIC-8301" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x8302, "MIC-8302" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x8304, "MIC-8304" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5101, "RTM-5101" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5102, "RTM-5102" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5106, "RTM-5106" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5107, "RTM-5107" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5210, "RTM-5210" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5220, "RTM-5220" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5104, "RTM-5104" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5500, "UTCA-5500"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x5503, "UTCA-5503"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x5504, "UTCA-5504"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x5801, "UTCA-5801"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x2210, "NCPB-2210"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x2305, "NCPB-2305"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x2320, "NCPB-2320"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x3109, "NCP-3109" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3110, "NCP-3110" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3200, "NCP-3200" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5060, "SMM-5060" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3210, "FWA-3210" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3220, "FWA-3220" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3221, "FWA-3221" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3230, "FWA-3230" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3231, "FWA-3231" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3233, "FWA-3233" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3250, "FWA-3250" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3260, "FWA-3260" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x5020, "FWA-5020" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6510, "FWA-6510" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6511, "FWA-6511" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6512, "FWA-6512" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6520, "FWA-6520" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6521, "FWA-6521" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6522, "FWA-6522" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x7310, "ATCA-7310"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x7330, "ATCA-7330"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x7410, "ATCA-7410"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x9023, "ATCA-9023"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x9112, "ATCA-9112"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x4201, "AMC-4201" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x4202, "AMC-4202" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x3211, "NAMB-3211"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x1207, "CPCI-1207"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x120E, "CPCI-1207 Test Board"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x1304, "CPCI-1304"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x7001, "CPCI-7001"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x8220, "CPCI-8220"},
|
|
+ { IPMI_OEM_ADVANTECH, 0x9001, "ESP-9001" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x9002, "ESP-9002" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x9012, "ESP-9012" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x9212, "ESP-9212" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6000, "CGS-6000" },
|
|
+ { IPMI_OEM_ADVANTECH, 0x6010, "CGS-6010" },
|
|
|
|
{ 0xffffff , 0xffff , NULL },
|
|
};
|
|
diff --git a/lib/ipmi_sunoem.c b/lib/ipmi_sunoem.c
|
|
index 16a6090..7f7a58b 100644
|
|
--- a/lib/ipmi_sunoem.c
|
|
+++ b/lib/ipmi_sunoem.c
|
|
@@ -1361,9 +1361,6 @@ ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[])
|
|
|
|
/* Fill in data packet */
|
|
for (i = 0; i < ECHO_DATA_SIZE; i++) {
|
|
- if (i > UINT8_MAX)
|
|
- break;
|
|
-
|
|
echo_req.data[i] = (uint8_t) i;
|
|
}
|
|
|
|
diff --git a/lib/ipmi_tsol.c b/lib/ipmi_tsol.c
|
|
index b4e3cc1..70d7357 100644
|
|
--- a/lib/ipmi_tsol.c
|
|
+++ b/lib/ipmi_tsol.c
|
|
@@ -29,6 +29,7 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _DEFAULT_SOURCE
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
@@ -184,12 +185,12 @@ print_escape_seq(struct ipmi_intf *intf)
|
|
" %c? - this message\n"
|
|
" %c%c - send the escape character by typing it twice\n"
|
|
" (Note that escapes are only recognized immediately after newline.)",
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char,
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char,
|
|
+ intf->ssn_params.sol_escape_char);
|
|
}
|
|
|
|
static int
|
|
@@ -263,7 +264,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
|
|
for(i = 0; i < len ;) {
|
|
if (!in_esc) {
|
|
if (last_was_cr &&
|
|
- (in_buff[i] == intf->session->sol_escape_char)) {
|
|
+ (in_buff[i] == intf->ssn_params.sol_escape_char)) {
|
|
in_esc = 1;
|
|
memmove(in_buff, in_buff + 1, len - i - 1);
|
|
len--;
|
|
@@ -271,7 +272,7 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
|
|
}
|
|
}
|
|
if (in_esc) {
|
|
- if (in_buff[i] == intf->session->sol_escape_char) {
|
|
+ if (in_buff[i] == intf->ssn_params.sol_escape_char) {
|
|
in_esc = 0;
|
|
i++;
|
|
continue;
|
|
@@ -280,23 +281,23 @@ do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
|
|
switch (in_buff[i]) {
|
|
case '.':
|
|
printf("%c. [terminated ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
return -1;
|
|
case 'Z' - 64:
|
|
printf("%c^Z [suspend ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
/* Restore tty back to raw */
|
|
suspend_self(1);
|
|
break;
|
|
case 'X' - 64:
|
|
printf("%c^X [suspend ipmitool]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
/* Don't restore to raw mode */
|
|
suspend_self(0);
|
|
break;
|
|
case '?':
|
|
printf("%c? [ipmitool help]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
print_escape_seq(intf);
|
|
break;
|
|
}
|
|
@@ -411,8 +412,10 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
print_tsol_usage();
|
|
return 0;
|
|
} else {
|
|
+ lprintf(LOG_ERR, "Invalid tsol command: '%s'\n",
|
|
+ argv[i]);
|
|
print_tsol_usage();
|
|
- return 0;
|
|
+ return (-1);
|
|
}
|
|
}
|
|
|
|
@@ -422,25 +425,25 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
sin.sin_port = htons(port);
|
|
|
|
sa_in = (struct sockaddr_in *)&intf->session->addr;
|
|
- result = inet_pton(AF_INET, (const char *)intf->session->hostname,
|
|
+ result = inet_pton(AF_INET, (const char *)intf->ssn_params.hostname,
|
|
&sa_in->sin_addr);
|
|
|
|
if (result <= 0) {
|
|
- struct hostent *host = gethostbyname((const char *)intf->session->hostname);
|
|
+ struct hostent *host = gethostbyname((const char *)intf->ssn_params.hostname);
|
|
if (host == NULL ) {
|
|
lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
- intf->session->hostname);
|
|
+ intf->ssn_params.hostname);
|
|
return -1;
|
|
}
|
|
if (host->h_addrtype != AF_INET) {
|
|
lprintf(LOG_ERR,
|
|
"Address lookup for %s failed. Got %s, expected IPv4 address.",
|
|
- intf->session->hostname,
|
|
+ intf->ssn_params.hostname,
|
|
(host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
|
|
return (-1);
|
|
}
|
|
sa_in->sin_family = host->h_addrtype;
|
|
- memcpy(&sa_in->sin_addr, host->h_addr, host->h_length);
|
|
+ memcpy(&sa_in->sin_addr, host->h_addr_list[0], host->h_length);
|
|
}
|
|
|
|
fd_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
@@ -498,7 +501,7 @@ ipmi_tsol_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
}
|
|
|
|
printf("[SOL Session operational. Use %c? for help]\n",
|
|
- intf->session->sol_escape_char);
|
|
+ intf->ssn_params.sol_escape_char);
|
|
|
|
gettimeofday(&_start_keepalive, 0);
|
|
|
|
diff --git a/lib/ipmi_user.c b/lib/ipmi_user.c
|
|
index d7e5890..6074209 100644
|
|
--- a/lib/ipmi_user.c
|
|
+++ b/lib/ipmi_user.c
|
|
@@ -53,249 +53,293 @@ extern int verbose;
|
|
extern int csv_output;
|
|
|
|
|
|
-#define IPMI_PASSWORD_DISABLE_USER 0x00
|
|
-#define IPMI_PASSWORD_ENABLE_USER 0x01
|
|
-#define IPMI_PASSWORD_SET_PASSWORD 0x02
|
|
-#define IPMI_PASSWORD_TEST_PASSWORD 0x03
|
|
-
|
|
-/*
|
|
- * ipmi_get_user_access
|
|
+/* _ipmi_get_user_access - Get User Access for given channel. Results are stored
|
|
+ * into passed struct.
|
|
*
|
|
- * param intf [in]
|
|
- * param channel_number [in]
|
|
- * param user_id [in]
|
|
- * param user_access [out]
|
|
+ * @intf - IPMI interface
|
|
+ * @user_access_rsp - ptr to user_access_t with UID and Channel set
|
|
*
|
|
- * return 0 on succes
|
|
- * 1 on failure
|
|
+ * returns - negative number means error, positive is a ccode
|
|
*/
|
|
-static int
|
|
-ipmi_get_user_access(
|
|
- struct ipmi_intf *intf,
|
|
- uint8_t channel_number,
|
|
- uint8_t user_id,
|
|
- struct user_access_rsp *user_access)
|
|
+int
|
|
+_ipmi_get_user_access(struct ipmi_intf *intf,
|
|
+ struct user_access_t *user_access_rsp)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t msg_data[2];
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
|
|
- req.msg.cmd = IPMI_GET_USER_ACCESS; /* 0x44 */
|
|
- req.msg.data = msg_data;
|
|
+ struct ipmi_rq req = {0};
|
|
+ struct ipmi_rs *rsp;
|
|
+ uint8_t data[2];
|
|
+ if (user_access_rsp == NULL) {
|
|
+ return (-3);
|
|
+ }
|
|
+ data[0] = user_access_rsp->channel & 0x0F;
|
|
+ data[1] = user_access_rsp->user_id & 0x3F;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_USER_ACCESS;
|
|
+ req.msg.data = data;
|
|
req.msg.data_len = 2;
|
|
-
|
|
-
|
|
- /* The channel number will remain constant throughout this function */
|
|
- msg_data[0] = channel_number;
|
|
- msg_data[1] = user_id;
|
|
-
|
|
rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Get User Access command failed "
|
|
- "(channel %d, user %d)", channel_number, user_id);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Get User Access command failed "
|
|
- "(channel %d, user %d): %s", channel_number, user_id,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ return rsp->ccode;
|
|
+ } else if (rsp->data_len != 4) {
|
|
+ return (-2);
|
|
}
|
|
-
|
|
- memcpy(user_access,
|
|
- rsp->data,
|
|
- sizeof(struct user_access_rsp));
|
|
-
|
|
- return 0;
|
|
+ user_access_rsp->max_user_ids = rsp->data[0] & 0x3F;
|
|
+ user_access_rsp->enable_status = rsp->data[1] & 0xC0;
|
|
+ user_access_rsp->enabled_user_ids = rsp->data[1] & 0x3F;
|
|
+ user_access_rsp->fixed_user_ids = rsp->data[2] & 0x3F;
|
|
+ user_access_rsp->callin_callback = rsp->data[3] & 0x40;
|
|
+ user_access_rsp->link_auth = rsp->data[3] & 0x20;
|
|
+ user_access_rsp->ipmi_messaging = rsp->data[3] & 0x10;
|
|
+ user_access_rsp->privilege_limit = rsp->data[3] & 0x0F;
|
|
+ return rsp->ccode;
|
|
}
|
|
|
|
-
|
|
-
|
|
-/*
|
|
- * ipmi_get_user_name
|
|
+/* _ipmi_get_user_name - Fetch User Name for given User ID. User Name is stored
|
|
+ * into passed structure.
|
|
*
|
|
- * param intf [in]
|
|
- * param channel_number [in]
|
|
- * param user_id [in]
|
|
- * param user_name [out]
|
|
+ * @intf - ipmi interface
|
|
+ * @user_name - user_name_t struct with UID set
|
|
*
|
|
- * return 0 on succes
|
|
- * 1 on failure
|
|
+ * returns - negative number means error, positive is a ccode
|
|
*/
|
|
-static int
|
|
-ipmi_get_user_name(
|
|
- struct ipmi_intf *intf,
|
|
- uint8_t user_id,
|
|
- char *user_name)
|
|
+int
|
|
+_ipmi_get_user_name(struct ipmi_intf *intf, struct user_name_t *user_name_ptr)
|
|
{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t msg_data[1];
|
|
-
|
|
- memset(user_name, 0, 17);
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
|
|
- req.msg.cmd = IPMI_GET_USER_NAME; /* 0x45 */
|
|
- req.msg.data = msg_data;
|
|
+ struct ipmi_rq req = {0};
|
|
+ struct ipmi_rs *rsp;
|
|
+ uint8_t data[1];
|
|
+ if (user_name_ptr == NULL) {
|
|
+ return (-3);
|
|
+ }
|
|
+ data[0] = user_name_ptr->user_id & 0x3F;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_GET_USER_NAME;
|
|
+ req.msg.data = data;
|
|
req.msg.data_len = 1;
|
|
-
|
|
- msg_data[0] = user_id;
|
|
-
|
|
rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Get User Name command failed (user %d)",
|
|
- user_id);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- if (rsp->ccode == 0xcc)
|
|
- return 0;
|
|
- lprintf(LOG_ERR, "Get User Name command failed (user %d): %s",
|
|
- user_id, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode > 0) {
|
|
+ return rsp->ccode;
|
|
+ } else if (rsp->data_len != 16) {
|
|
+ return (-2);
|
|
}
|
|
-
|
|
- memcpy(user_name, rsp->data, 16);
|
|
-
|
|
- return 0;
|
|
+ memset(user_name_ptr->user_name, '\0', 17);
|
|
+ memcpy(user_name_ptr->user_name, rsp->data, 16);
|
|
+ return rsp->ccode;
|
|
}
|
|
|
|
+/* _ipmi_set_user_access - Set User Access for given channel.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @user_access_req - ptr to user_access_t with desired User Access.
|
|
+ * @change_priv_limit_only - change User's privilege limit only
|
|
+ *
|
|
+ * returns - negative number means error, positive is a ccode
|
|
+ */
|
|
+int
|
|
+_ipmi_set_user_access(struct ipmi_intf *intf,
|
|
+ struct user_access_t *user_access_req,
|
|
+ uint8_t change_priv_limit_only)
|
|
+{
|
|
+ uint8_t data[4];
|
|
+ struct ipmi_rq req = {0};
|
|
+ struct ipmi_rs *rsp;
|
|
+ if (user_access_req == NULL) {
|
|
+ return (-3);
|
|
+ }
|
|
+ data[0] = change_priv_limit_only ? 0x00 : 0x80;
|
|
+ if (user_access_req->callin_callback) {
|
|
+ data[0] |= 0x40;
|
|
+ }
|
|
+ if (user_access_req->link_auth) {
|
|
+ data[0] |= 0x20;
|
|
+ }
|
|
+ if (user_access_req->ipmi_messaging) {
|
|
+ data[0] |= 0x10;
|
|
+ }
|
|
+ data[0] |= (user_access_req->channel & 0x0F);
|
|
+ data[1] = user_access_req->user_id & 0x3F;
|
|
+ data[2] = user_access_req->privilege_limit & 0x0F;
|
|
+ data[3] = user_access_req->session_limit & 0x0F;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_SET_USER_ACCESS;
|
|
+ req.msg.data = data;
|
|
+ req.msg.data_len = 4;
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ return (-1);
|
|
+ } else {
|
|
+ return rsp->ccode;
|
|
+ }
|
|
+}
|
|
|
|
+/* _ipmi_set_user_password - Set User Password command.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @user_id - IPMI User ID
|
|
+ * @operation - which operation to perform(en/disable user, set/test password)
|
|
+ * @password - User Password
|
|
+ * @is_twenty_byte - 0 = store as 16byte, otherwise store as 20byte password
|
|
+ *
|
|
+ * returns - negative number means error, positive is a ccode
|
|
+ */
|
|
+int
|
|
+_ipmi_set_user_password(struct ipmi_intf *intf, uint8_t user_id,
|
|
+ uint8_t operation, const char *password,
|
|
+ uint8_t is_twenty_byte)
|
|
+{
|
|
+ struct ipmi_rq req = {0};
|
|
+ struct ipmi_rs *rsp;
|
|
+ uint8_t *data;
|
|
+ uint8_t data_len = (is_twenty_byte) ? 22 : 18;
|
|
+ data = malloc(sizeof(uint8_t) * data_len);
|
|
+ if (data == NULL) {
|
|
+ return (-4);
|
|
+ }
|
|
+ memset(data, 0, data_len);
|
|
+ data[0] = (is_twenty_byte) ? 0x80 : 0x00;
|
|
+ data[0] |= (0x0F & user_id);
|
|
+ data[1] = 0x03 & operation;
|
|
+ if (password != NULL) {
|
|
+ size_t copy_len = strlen(password);
|
|
+ if (copy_len > (data_len - 2)) {
|
|
+ copy_len = data_len - 2;
|
|
+ } else if (copy_len < 1) {
|
|
+ copy_len = 0;
|
|
+ }
|
|
+ strncpy((char *)(data + 2), password, copy_len);
|
|
+ }
|
|
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_SET_USER_PASSWORD;
|
|
+ req.msg.data = data;
|
|
+ req.msg.data_len = data_len;
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ free(data);
|
|
+ data = NULL;
|
|
+ if (rsp == NULL) {
|
|
+ return (-1);
|
|
+ }
|
|
+ return rsp->ccode;
|
|
+}
|
|
|
|
static void
|
|
-dump_user_access(
|
|
- uint8_t user_id,
|
|
- const char * user_name,
|
|
- struct user_access_rsp * user_access)
|
|
+dump_user_access(const char *user_name,
|
|
+ struct user_access_t *user_access)
|
|
{
|
|
static int printed_header = 0;
|
|
-
|
|
- if (! printed_header)
|
|
- {
|
|
+ if (!printed_header) {
|
|
printf("ID Name Callin Link Auth IPMI Msg "
|
|
- "Channel Priv Limit\n");
|
|
+ "Channel Priv Limit\n");
|
|
printed_header = 1;
|
|
}
|
|
-
|
|
printf("%-4d%-17s%-8s%-11s%-11s%-s\n",
|
|
- user_id,
|
|
- user_name,
|
|
- user_access->no_callin_access? "false": "true ",
|
|
- user_access->link_auth_access? "true ": "false",
|
|
- user_access->ipmi_messaging_access? "true ": "false",
|
|
- val2str(user_access->channel_privilege_limit,
|
|
- ipmi_privlvl_vals));
|
|
+ user_access->user_id,
|
|
+ user_name,
|
|
+ user_access->callin_callback? "false": "true ",
|
|
+ user_access->link_auth? "true ": "false",
|
|
+ user_access->ipmi_messaging? "true ": "false",
|
|
+ val2str(user_access->privilege_limit,
|
|
+ ipmi_privlvl_vals));
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
-dump_user_access_csv(
|
|
- uint8_t user_id,
|
|
- const char *user_name,
|
|
- struct user_access_rsp *user_access)
|
|
+dump_user_access_csv(const char *user_name,
|
|
+ struct user_access_t *user_access)
|
|
{
|
|
printf("%d,%s,%s,%s,%s,%s\n",
|
|
- user_id,
|
|
- user_name,
|
|
- user_access->no_callin_access? "false": "true",
|
|
- user_access->link_auth_access? "true": "false",
|
|
- user_access->ipmi_messaging_access? "true": "false",
|
|
- val2str(user_access->channel_privilege_limit,
|
|
- ipmi_privlvl_vals));
|
|
+ user_access->user_id,
|
|
+ user_name,
|
|
+ user_access->callin_callback? "false": "true",
|
|
+ user_access->link_auth? "true": "false",
|
|
+ user_access->ipmi_messaging? "true": "false",
|
|
+ val2str(user_access->privilege_limit,
|
|
+ ipmi_privlvl_vals));
|
|
}
|
|
|
|
+/* ipmi_print_user_list - List IPMI Users and their ACLs for given channel.
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel_number - IPMI channel
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error
|
|
+ */
|
|
static int
|
|
-ipmi_print_user_list(
|
|
- struct ipmi_intf *intf,
|
|
- uint8_t channel_number)
|
|
+ipmi_print_user_list(struct ipmi_intf *intf, uint8_t channel_number)
|
|
{
|
|
- /* This is where you were! */
|
|
- char user_name[17];
|
|
- struct user_access_rsp user_access;
|
|
+ struct user_access_t user_access = {0};
|
|
+ struct user_name_t user_name = {0};
|
|
+ int ccode = 0;
|
|
uint8_t current_user_id = 1;
|
|
-
|
|
-
|
|
- do
|
|
- {
|
|
- if (ipmi_get_user_access(intf,
|
|
- channel_number,
|
|
- current_user_id,
|
|
- &user_access))
|
|
- return -1;
|
|
-
|
|
-
|
|
- if (ipmi_get_user_name(intf,
|
|
- current_user_id,
|
|
- user_name))
|
|
- return -1;
|
|
-
|
|
- if ((current_user_id == 0) ||
|
|
- user_access.link_auth_access ||
|
|
- user_access.ipmi_messaging_access ||
|
|
- strcmp("", user_name))
|
|
- {
|
|
- if (csv_output)
|
|
- dump_user_access_csv(current_user_id,
|
|
- user_name, &user_access);
|
|
- else
|
|
- dump_user_access(current_user_id,
|
|
- user_name,
|
|
- &user_access);
|
|
+ do {
|
|
+ memset(&user_access, 0, sizeof(user_access));
|
|
+ user_access.user_id = current_user_id;
|
|
+ user_access.channel = channel_number;
|
|
+ ccode = _ipmi_get_user_access(intf, &user_access);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ memset(&user_name, 0, sizeof(user_name));
|
|
+ user_name.user_id = current_user_id;
|
|
+ ccode = _ipmi_get_user_name(intf, &user_name);
|
|
+ if (ccode == 0xCC) {
|
|
+ user_name.user_id = current_user_id;
|
|
+ memset(&user_name.user_name, '\0', 17);
|
|
+ } else if (eval_ccode(ccode) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (csv_output) {
|
|
+ dump_user_access_csv((char *)user_name.user_name,
|
|
+ &user_access);
|
|
+ } else {
|
|
+ dump_user_access((char *)user_name.user_name,
|
|
+ &user_access);
|
|
}
|
|
-
|
|
-
|
|
++current_user_id;
|
|
- } while((current_user_id <= user_access.maximum_ids) &&
|
|
- (current_user_id <= IPMI_UID_MAX)); /* Absolute maximum allowed by spec */
|
|
-
|
|
-
|
|
+ } while ((current_user_id <= user_access.max_user_ids)
|
|
+ && (current_user_id <= IPMI_UID_MAX));
|
|
return 0;
|
|
}
|
|
|
|
-
|
|
-
|
|
+/* ipmi_print_user_summary - print User statistics for given channel
|
|
+ *
|
|
+ * @intf - IPMI interface
|
|
+ * @channel_number - channel number
|
|
+ *
|
|
+ * returns - 0 on success, (-1) on error
|
|
+ */
|
|
static int
|
|
-ipmi_print_user_summary(
|
|
- struct ipmi_intf * intf,
|
|
- uint8_t channel_number)
|
|
+ipmi_print_user_summary(struct ipmi_intf *intf, uint8_t channel_number)
|
|
{
|
|
- struct user_access_rsp user_access;
|
|
-
|
|
- if (ipmi_get_user_access(intf,
|
|
- channel_number,
|
|
- 1,
|
|
- &user_access))
|
|
- return -1;
|
|
-
|
|
- if (csv_output)
|
|
- {
|
|
- printf("%d,%d,%d\n",
|
|
- user_access.maximum_ids,
|
|
- user_access.enabled_user_count,
|
|
- user_access.fixed_name_count);
|
|
+ struct user_access_t user_access = {0};
|
|
+ int ccode = 0;
|
|
+ user_access.channel = channel_number;
|
|
+ user_access.user_id = 1;
|
|
+ ccode = _ipmi_get_user_access(intf, &user_access);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ return (-1);
|
|
}
|
|
- else
|
|
- {
|
|
- printf("Maximum IDs : %d\n",
|
|
- user_access.maximum_ids);
|
|
- printf("Enabled User Count : %d\n",
|
|
- user_access.enabled_user_count);
|
|
- printf("Fixed Name Count : %d\n",
|
|
- user_access.fixed_name_count);
|
|
+ if (csv_output) {
|
|
+ printf("%" PRIu8 ",%" PRIu8 ",%" PRIu8 "\n",
|
|
+ user_access.max_user_ids,
|
|
+ user_access.enabled_user_ids,
|
|
+ user_access.fixed_user_ids);
|
|
+ } else {
|
|
+ printf("Maximum IDs : %" PRIu8 "\n",
|
|
+ user_access.max_user_ids);
|
|
+ printf("Enabled User Count : %" PRIu8 "\n",
|
|
+ user_access.enabled_user_ids);
|
|
+ printf("Fixed Name Count : %" PRIu8 "\n",
|
|
+ user_access.fixed_user_ids);
|
|
}
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
-
|
|
-
|
|
/*
|
|
* ipmi_user_set_username
|
|
*/
|
|
@@ -343,125 +387,17 @@ ipmi_user_set_username(
|
|
return 0;
|
|
}
|
|
|
|
-static int
|
|
-ipmi_user_set_userpriv(
|
|
- struct ipmi_intf *intf,
|
|
- uint8_t channel,
|
|
- uint8_t user_id,
|
|
- const unsigned char privLevel)
|
|
-{
|
|
- struct ipmi_rs *rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t msg_data[4] = {0, 0, 0, 0};
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
|
|
- req.msg.cmd = IPMI_SET_USER_ACCESS; /* 0x43 */
|
|
- req.msg.data = msg_data;
|
|
- req.msg.data_len = 4;
|
|
-
|
|
- /* The channel number will remain constant throughout this function */
|
|
- msg_data[0] = (channel & 0x0f);
|
|
- msg_data[1] = (user_id & 0x3f);
|
|
- msg_data[2] = (privLevel & 0x0f);
|
|
- msg_data[3] = 0;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (rsp == NULL)
|
|
- {
|
|
- lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)",
|
|
- user_id);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "Set Privilege Level command failed (user %d): %s",
|
|
- user_id, val2str(rsp->ccode, completion_code_vals));
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * ipmi_user_set_password
|
|
- *
|
|
- * This function is responsible for 4 things
|
|
- * Enabling/Disabling users
|
|
- * Setting/Testing passwords
|
|
- */
|
|
-static int
|
|
-ipmi_user_set_password(
|
|
- struct ipmi_intf * intf,
|
|
- uint8_t user_id,
|
|
- uint8_t operation,
|
|
- const char *password,
|
|
- int is_twenty_byte_password)
|
|
-{
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t msg_data[22];
|
|
-
|
|
- int password_length = (is_twenty_byte_password? 20 : 16);
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
|
|
- req.msg.cmd = IPMI_SET_USER_PASSWORD; /* 0x47 */
|
|
- req.msg.data = msg_data;
|
|
- req.msg.data_len = password_length + 2;
|
|
-
|
|
-
|
|
- /* The channel number will remain constant throughout this function */
|
|
- msg_data[0] = user_id;
|
|
-
|
|
- if (is_twenty_byte_password)
|
|
- msg_data[0] |= 0x80;
|
|
-
|
|
- msg_data[1] = operation;
|
|
-
|
|
- memset(msg_data + 2, 0, password_length);
|
|
-
|
|
- if (password != NULL)
|
|
- strncpy((char *)(msg_data + 2), password, password_length);
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, "Set User Password command failed (user %d)",
|
|
- user_id);
|
|
- return -1;
|
|
- }
|
|
- if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR, "Set User Password command failed (user %d): %s",
|
|
- user_id, val2str(rsp->ccode, completion_code_vals));
|
|
- return rsp->ccode;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-
|
|
-/*
|
|
- * ipmi_user_test_password
|
|
- *
|
|
- * Call ipmi_user_set_password, and interpret the result
|
|
+/* ipmi_user_test_password - Call _ipmi_set_user_password() with operation bit
|
|
+ * set to test password and interpret result.
|
|
*/
|
|
static int
|
|
-ipmi_user_test_password(
|
|
- struct ipmi_intf * intf,
|
|
- uint8_t user_id,
|
|
- const char * password,
|
|
- int is_twenty_byte_password)
|
|
+ipmi_user_test_password(struct ipmi_intf *intf, uint8_t user_id,
|
|
+ const char *password, uint8_t is_twenty_byte_password)
|
|
{
|
|
- int ret;
|
|
-
|
|
- ret = ipmi_user_set_password(intf,
|
|
- user_id,
|
|
- IPMI_PASSWORD_TEST_PASSWORD,
|
|
- password,
|
|
- is_twenty_byte_password);
|
|
+ int ret = 0;
|
|
+ ret = _ipmi_set_user_password(intf, user_id,
|
|
+ IPMI_PASSWORD_TEST_PASSWORD, password,
|
|
+ is_twenty_byte_password);
|
|
|
|
switch (ret) {
|
|
case 0:
|
|
@@ -487,16 +423,40 @@ ipmi_user_test_password(
|
|
static void
|
|
print_user_usage(void)
|
|
{
|
|
- lprintf(LOG_NOTICE, "User Commands:");
|
|
- lprintf(LOG_NOTICE, " summary [<channel number>]");
|
|
- lprintf(LOG_NOTICE, " list [<channel number>]");
|
|
- lprintf(LOG_NOTICE, " set name <user id> <username>");
|
|
- lprintf(LOG_NOTICE, " set password <user id> [<password>]");
|
|
- lprintf(LOG_NOTICE, " disable <user id>");
|
|
- lprintf(LOG_NOTICE, " enable <user id>");
|
|
lprintf(LOG_NOTICE,
|
|
- " priv <user id> <privilege level> [<channel number>]");
|
|
- lprintf(LOG_NOTICE, " test <user id> <16|20> [<password]>\n");
|
|
+"User Commands:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" summary [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" list [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" set name <user id> <username>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" set password <user id> [<password> <16|20>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" disable <user id>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" enable <user id>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" priv <user id> <privilege level> [<channel number>]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Privilege levels:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0x1 - Callback");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0x2 - User");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0x3 - Operator");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0x4 - Administrator");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0x5 - OEM Proprietary");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" * 0xF - No Access");
|
|
+ lprintf(LOG_NOTICE, "");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" test <user id> <16|20> [<password]>");
|
|
+ lprintf(LOG_NOTICE, "");
|
|
}
|
|
|
|
|
|
@@ -509,328 +469,282 @@ ipmi_user_build_password_prompt(uint8_t user_id)
|
|
return prompt;
|
|
}
|
|
|
|
-
|
|
-/*
|
|
- * ipmi_user_main
|
|
+/* ask_password - ask user for password
|
|
*
|
|
- * Upon entry to this function argv should contain our arguments
|
|
- * specific to this subcommand
|
|
+ * @user_id: User ID which will be built-in into text
|
|
+ *
|
|
+ * @returns pointer to char with password
|
|
*/
|
|
-int
|
|
-ipmi_user_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
+char *
|
|
+ask_password(uint8_t user_id)
|
|
{
|
|
- int retval = 0;
|
|
+ const char *password_prompt =
|
|
+ ipmi_user_build_password_prompt(user_id);
|
|
+# ifdef HAVE_GETPASSPHRASE
|
|
+ return getpassphrase(password_prompt);
|
|
+# else
|
|
+ return (char*)getpass(password_prompt);
|
|
+# endif
|
|
+}
|
|
|
|
- /*
|
|
- * Help
|
|
- */
|
|
- if (argc == 0 || strncmp(argv[0], "help", 4) == 0)
|
|
- {
|
|
+int
|
|
+ipmi_user_summary(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ /* Summary*/
|
|
+ uint8_t channel;
|
|
+ if (argc == 1) {
|
|
+ channel = 0x0E; /* Ask about the current channel */
|
|
+ } else if (argc == 2) {
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ } else {
|
|
print_user_usage();
|
|
+ return (-1);
|
|
}
|
|
+ return ipmi_print_user_summary(intf, channel);
|
|
+}
|
|
|
|
- /*
|
|
- * Summary
|
|
- */
|
|
- else if (strncmp(argv[0], "summary", 7) == 0)
|
|
- {
|
|
- uint8_t channel;
|
|
-
|
|
- if (argc == 1)
|
|
- channel = 0x0E; /* Ask about the current channel */
|
|
- else if (argc == 2)
|
|
- {
|
|
- if (str2uchar(argv[1], &channel) != 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
|
|
- return (-1);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
+int
|
|
+ipmi_user_list(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ /* List */
|
|
+ uint8_t channel;
|
|
+ if (argc == 1) {
|
|
+ channel = 0x0E; /* Ask about the current channel */
|
|
+ } else if (argc == 2) {
|
|
+ if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- retval = ipmi_print_user_summary(intf, channel);
|
|
+ } else {
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
}
|
|
+ return ipmi_print_user_list(intf, channel);
|
|
+}
|
|
|
|
-
|
|
- /*
|
|
- * List
|
|
- */
|
|
- else if (strncmp(argv[0], "list", 4) == 0)
|
|
- {
|
|
- uint8_t channel;
|
|
-
|
|
- if (argc == 1)
|
|
- channel = 0x0E; /* Ask about the current channel */
|
|
- else if (argc == 2)
|
|
- {
|
|
- if (str2uchar(argv[1], &channel) != 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
|
|
- return (-1);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
+int
|
|
+ipmi_user_test(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ /* Test */
|
|
+ char *password = NULL;
|
|
+ int password_length = 0;
|
|
+ uint8_t user_id = 0;
|
|
+ /* a little irritating, isn't it */
|
|
+ if (argc != 3 && argc != 4) {
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (is_ipmi_user_id(argv[1], &user_id)) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (str2int(argv[2], &password_length) != 0
|
|
+ || (password_length != 16 && password_length != 20)) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given password length '%s' is invalid.",
|
|
+ argv[2]);
|
|
+ lprintf(LOG_ERR, "Expected value is either 16 or 20.");
|
|
+ return (-1);
|
|
+ }
|
|
+ if (argc == 3) {
|
|
+ /* We need to prompt for a password */
|
|
+ password = ask_password(user_id);
|
|
+ if (password == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- retval = ipmi_print_user_list(intf, channel);
|
|
+ } else {
|
|
+ password = argv[3];
|
|
}
|
|
+ return ipmi_user_test_password(intf,
|
|
+ user_id,
|
|
+ password,
|
|
+ password_length == 20);
|
|
+}
|
|
|
|
+int
|
|
+ipmi_user_priv(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ struct user_access_t user_access = {0};
|
|
+ int ccode = 0;
|
|
|
|
-
|
|
- /*
|
|
- * Test
|
|
- */
|
|
- else if (strncmp(argv[0], "test", 4) == 0)
|
|
- {
|
|
- // a little irritating, isn't it
|
|
- if (argc == 3 || argc == 4)
|
|
- {
|
|
- char * password = NULL;
|
|
- int password_length = 0;
|
|
- uint8_t user_id = 0;
|
|
- if (is_ipmi_user_id(argv[1], &user_id)) {
|
|
- return (-1);
|
|
- }
|
|
- if (str2int(argv[2], &password_length) != 0
|
|
- || (password_length != 16 && password_length != 20)) {
|
|
- lprintf(LOG_ERR,
|
|
- "Given password length '%s' is invalid.",
|
|
- argv[2]);
|
|
- lprintf(LOG_ERR, "Expected value is either 16 or 20.");
|
|
- return (-1);
|
|
- }
|
|
-
|
|
- if (argc == 3)
|
|
- {
|
|
- /* We need to prompt for a password */
|
|
-
|
|
- char * tmp;
|
|
- const char * password_prompt =
|
|
- ipmi_user_build_password_prompt(user_id);
|
|
-# ifdef HAVE_GETPASSPHRASE
|
|
- tmp = getpassphrase (password_prompt);
|
|
-# else
|
|
- tmp = (char*)getpass (password_prompt);
|
|
-# endif
|
|
- if (tmp != NULL) {
|
|
- password = strdup(tmp);
|
|
- tmp = NULL;
|
|
- }
|
|
- if (password == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
- }
|
|
- else {
|
|
- password = strdup(argv[3]);
|
|
- }
|
|
-
|
|
-
|
|
- retval = ipmi_user_test_password(intf,
|
|
- user_id,
|
|
- password,
|
|
- password_length == 20);
|
|
- if (password != NULL) {
|
|
- free(password);
|
|
- password = NULL;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
+ if (argc != 3 && argc != 4) {
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (argc == 4) {
|
|
+ if (is_ipmi_channel_num(argv[3], &user_access.channel) != 0) {
|
|
+ return (-1);
|
|
}
|
|
+ } else {
|
|
+ /* Use channel running on */
|
|
+ user_access.channel = 0x0E;
|
|
}
|
|
+ if (is_ipmi_user_priv_limit(argv[2], &user_access.privilege_limit) != 0
|
|
+ || is_ipmi_user_id(argv[1], &user_access.user_id) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ ccode = _ipmi_set_user_access(intf, &user_access, 1);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)",
|
|
+ user_access.user_id);
|
|
+ return (-1);
|
|
+ } else {
|
|
+ printf("Set Privilege Level command successful (user %d)",
|
|
+ user_access.user_id);
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
|
|
- /*
|
|
- * Set
|
|
- */
|
|
- else if (strncmp(argv[0], "set", 3) == 0)
|
|
- {
|
|
- /*
|
|
- * Set Password
|
|
- */
|
|
- if ((argc >= 3) &&
|
|
- (strncmp("password", argv[1], 8) == 0))
|
|
- {
|
|
- char * password = NULL;
|
|
- uint8_t user_id = 0;
|
|
- if (is_ipmi_user_id(argv[2], &user_id)) {
|
|
- return (-1);
|
|
- }
|
|
-
|
|
- if (argc == 3)
|
|
- {
|
|
- /* We need to prompt for a password */
|
|
- char * tmp;
|
|
- const char * password_prompt =
|
|
- ipmi_user_build_password_prompt(user_id);
|
|
-# ifdef HAVE_GETPASSPHRASE
|
|
- tmp = getpassphrase (password_prompt);
|
|
-# else
|
|
- tmp = (char*)getpass (password_prompt);
|
|
-# endif
|
|
- if (tmp != NULL) {
|
|
- password = strdup(tmp);
|
|
- tmp = NULL;
|
|
- }
|
|
- if (password == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
-# ifdef HAVE_GETPASSPHRASE
|
|
- tmp = getpassphrase (password_prompt);
|
|
-# else
|
|
- tmp = (char*)getpass (password_prompt);
|
|
-# endif
|
|
- if (tmp == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return (-1);
|
|
- }
|
|
- if (strlen(password) != strlen(tmp)
|
|
- || strncmp(password, tmp, strlen(tmp))) {
|
|
- lprintf(LOG_ERR, "Passwords do not match.");
|
|
- free(password);
|
|
- password = NULL;
|
|
- return -1;
|
|
- }
|
|
- tmp = NULL;
|
|
- } else {
|
|
- password = strdup(argv[3]);
|
|
- }
|
|
-
|
|
- if (password == NULL) {
|
|
- lprintf(LOG_ERR, "Unable to parse password argument.");
|
|
- return -1;
|
|
- }
|
|
- else if (strlen(password) > 20)
|
|
- {
|
|
- lprintf(LOG_ERR, "Password is too long (> 20 bytes)");
|
|
- return -1;
|
|
- }
|
|
+int
|
|
+ipmi_user_mod(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ /* Disable / Enable */
|
|
+ uint8_t user_id;
|
|
+ uint8_t operation;
|
|
|
|
- retval = ipmi_user_set_password(intf,
|
|
- user_id,
|
|
- IPMI_PASSWORD_SET_PASSWORD,
|
|
- password,
|
|
- strlen(password) > 16);
|
|
- if (password != NULL) {
|
|
- free(password);
|
|
- password = NULL;
|
|
- }
|
|
- }
|
|
+ if (argc != 2) {
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (is_ipmi_user_id(argv[1], &user_id)) {
|
|
+ return (-1);
|
|
+ }
|
|
+ operation = (strncmp(argv[0], "disable", 7) == 0) ?
|
|
+ IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER;
|
|
|
|
- /*
|
|
- * Set Name
|
|
- */
|
|
- else if ((argc >= 2) &&
|
|
- (strncmp("name", argv[1], 4) == 0))
|
|
- {
|
|
- uint8_t user_id = 0;
|
|
- if (argc != 4)
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
- }
|
|
- if (is_ipmi_user_id(argv[2], &user_id)) {
|
|
- return (-1);
|
|
- }
|
|
+ return _ipmi_set_user_password(intf, user_id, operation,
|
|
+ (char *)NULL, 0);
|
|
+}
|
|
|
|
- if (strlen(argv[3]) > 16)
|
|
- {
|
|
- lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
|
|
- return -1;
|
|
- }
|
|
+int
|
|
+ipmi_user_password(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ char *password = NULL;
|
|
+ int ccode = 0;
|
|
+ uint8_t password_type = 16;
|
|
+ uint8_t user_id = 0;
|
|
+ if (is_ipmi_user_id(argv[2], &user_id)) {
|
|
+ return (-1);
|
|
+ }
|
|
|
|
- retval = ipmi_user_set_username(intf, user_id, argv[3]);
|
|
+ if (argc == 3) {
|
|
+ /* We need to prompt for a password */
|
|
+ char *tmp;
|
|
+ password = ask_password(user_id);
|
|
+ if (password == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return (-1);
|
|
}
|
|
- else
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
+ tmp = ask_password(user_id);
|
|
+ if (tmp == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return (-1);
|
|
}
|
|
- }
|
|
-
|
|
- else if (strncmp(argv[0], "priv", 4) == 0)
|
|
- {
|
|
- uint8_t user_id;
|
|
- uint8_t priv_level;
|
|
- uint8_t channel = 0x0e; /* Use channel running on */
|
|
-
|
|
- if (argc != 3 && argc != 4)
|
|
- {
|
|
- print_user_usage();
|
|
- return -1;
|
|
+ if (strlen(password) != strlen(tmp)
|
|
+ || strncmp(password, tmp, strlen(tmp))) {
|
|
+ lprintf(LOG_ERR, "Passwords do not match.");
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- if (argc == 4)
|
|
- {
|
|
- if (str2uchar(argv[3], &channel) != 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "Invalid channel: %s", argv[3]);
|
|
+ } else {
|
|
+ password = argv[3];
|
|
+ if (argc > 4) {
|
|
+ if ((str2uchar(argv[4], &password_type) != 0)
|
|
+ || (password_type != 16 && password_type != 20)) {
|
|
+ lprintf(LOG_ERR, "Invalid password length '%s'", argv[4]);
|
|
return (-1);
|
|
}
|
|
- channel = (channel & 0x0f);
|
|
+ } else {
|
|
+ password_type = 16;
|
|
}
|
|
-
|
|
- if (str2uchar(argv[2], &priv_level) != 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "Invalid privilege level: %s", argv[2]);
|
|
- return (-1);
|
|
- }
|
|
- priv_level = (priv_level & 0x0f);
|
|
+ }
|
|
|
|
- if (is_ipmi_user_id(argv[1], &user_id)) {
|
|
- return (-1);
|
|
- }
|
|
+ if (password == NULL) {
|
|
+ lprintf(LOG_ERR, "Unable to parse password argument.");
|
|
+ return (-1);
|
|
+ } else if (strlen(password) > 20) {
|
|
+ lprintf(LOG_ERR, "Password is too long (> 20 bytes)");
|
|
+ return (-1);
|
|
+ }
|
|
|
|
- retval = ipmi_user_set_userpriv(intf,channel,user_id,priv_level);
|
|
+ ccode = _ipmi_set_user_password(intf, user_id,
|
|
+ IPMI_PASSWORD_SET_PASSWORD, password,
|
|
+ password_type > 16);
|
|
+ if (eval_ccode(ccode) != 0) {
|
|
+ lprintf(LOG_ERR, "Set User Password command failed (user %d)",
|
|
+ user_id);
|
|
+ return (-1);
|
|
+ } else {
|
|
+ printf("Set User Password command successful (user %d)\n",
|
|
+ user_id);
|
|
+ return 0;
|
|
}
|
|
+}
|
|
|
|
- /*
|
|
- * Disable / Enable
|
|
- */
|
|
- else if ((strncmp(argv[0], "disable", 7) == 0) ||
|
|
- (strncmp(argv[0], "enable", 6) == 0))
|
|
- {
|
|
- uint8_t user_id;
|
|
- uint8_t operation;
|
|
- char null_password[16]; /* Not used, but required */
|
|
+int
|
|
+ipmi_user_name(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ /* Set Name */
|
|
+ uint8_t user_id = 0;
|
|
+ if (argc != 4) {
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (is_ipmi_user_id(argv[2], &user_id)) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (strlen(argv[3]) > 16) {
|
|
+ lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
|
|
+ return (-1);
|
|
+ }
|
|
|
|
- memset(null_password, 0, sizeof(null_password));
|
|
+ return ipmi_user_set_username(intf, user_id, argv[3]);
|
|
+}
|
|
|
|
- if (argc != 2)
|
|
- {
|
|
+/*
|
|
+ * ipmi_user_main
|
|
+ *
|
|
+ * Upon entry to this function argv should contain our arguments
|
|
+ * specific to this subcommand
|
|
+ */
|
|
+int
|
|
+ipmi_user_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ if (argc == 0) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
+ print_user_usage();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (strncmp(argv[0], "help", 4) == 0) {
|
|
+ /* Help */
|
|
+ print_user_usage();
|
|
+ return 0;
|
|
+ } else if (strncmp(argv[0], "summary", 7) == 0) {
|
|
+ return ipmi_user_summary(intf, argc, argv);
|
|
+ } else if (strncmp(argv[0], "list", 4) == 0) {
|
|
+ return ipmi_user_list(intf, argc, argv);
|
|
+ } else if (strncmp(argv[0], "test", 4) == 0) {
|
|
+ return ipmi_user_test(intf, argc, argv);
|
|
+ } else if (strncmp(argv[0], "set", 3) == 0) {
|
|
+ /* Set */
|
|
+ if ((argc >= 3)
|
|
+ && (strncmp("password", argv[1], 8) == 0)) {
|
|
+ return ipmi_user_password(intf, argc, argv);
|
|
+ } else if ((argc >= 2)
|
|
+ && (strncmp("name", argv[1], 4) == 0)) {
|
|
+ return ipmi_user_name(intf, argc, argv);
|
|
+ } else {
|
|
print_user_usage();
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if (is_ipmi_user_id(argv[1], &user_id)) {
|
|
return (-1);
|
|
}
|
|
-
|
|
- operation = (strncmp(argv[0], "disable", 7) == 0) ?
|
|
- IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER;
|
|
-
|
|
- retval = ipmi_user_set_password(intf,
|
|
- user_id,
|
|
- operation,
|
|
- null_password,
|
|
- 0); /* This field is ignored */
|
|
- }
|
|
- else
|
|
- {
|
|
- retval = -1;
|
|
+ } else if (strncmp(argv[0], "priv", 4) == 0) {
|
|
+ return ipmi_user_priv(intf, argc, argv);
|
|
+ } else if ((strncmp(argv[0], "disable", 7) == 0)
|
|
+ || (strncmp(argv[0], "enable", 6) == 0)) {
|
|
+ return ipmi_user_mod(intf, argc, argv);
|
|
+ } else {
|
|
lprintf(LOG_ERR, "Invalid user command: '%s'\n", argv[0]);
|
|
print_user_usage();
|
|
+ return (-1);
|
|
}
|
|
-
|
|
- return retval;
|
|
}
|
|
diff --git a/lib/ipmi_vita.c b/lib/ipmi_vita.c
|
|
new file mode 100644
|
|
index 0000000..45ddd3e
|
|
--- /dev/null
|
|
+++ b/lib/ipmi_vita.c
|
|
@@ -0,0 +1,1012 @@
|
|
+/*
|
|
+ * Copyright (c) 2014 Pigeon Point Systems. All right reserved
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ *
|
|
+ * Redistribution of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ *
|
|
+ * Redistribution in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ *
|
|
+ * Neither the name of Pigeon Point Systems, or the names of
|
|
+ * contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * This software is provided "AS IS, " without a warranty of any kind.
|
|
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
+ * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
|
|
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
|
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
|
+ * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
|
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
|
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
|
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
+ * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ */
|
|
+
|
|
+
|
|
+#include <ipmitool/ipmi_intf.h>
|
|
+#include <ipmitool/ipmi_picmg.h>
|
|
+#include <ipmitool/ipmi_vita.h>
|
|
+#include <ipmitool/ipmi_fru.h>
|
|
+#include <ipmitool/ipmi_strings.h>
|
|
+#include <ipmitool/log.h>
|
|
+
|
|
+/* 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 <FRU-ID> <OPTION>\n"
|
|
+ " OPTION: 0 - Cold Reset\n"
|
|
+ " 1 - Warm Reset\n"
|
|
+ " 2 - Graceful Reboot\n"
|
|
+ " 3 - Issue Diagnostic Interrupt"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_ADDRINFO,
|
|
+ "usage: addrinfo [<FRU-ID>]"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_ACTIVATE,
|
|
+ "usage: activate <FRU-ID>"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_DEACTIVATE,
|
|
+ "usage: deactivate <FRU-ID>"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_POLICY_GET,
|
|
+ "usage: policy get <FRU-ID>"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_POLICY_SET,
|
|
+ "usage: policy set <FRU-ID> <MASK> <VALUE>\n"
|
|
+ " MASK: [3] affect the Default-Activation-Locked Policy Bit\n"
|
|
+ " [2] affect the Commanded-Deactivation-Ignored Policy Bit\n"
|
|
+ " [1] affect the Deactivation-Locked Policy Bit\n"
|
|
+ " [0] affect the Activation-Locked Policy Bit\n"
|
|
+ " VALUE: [3] value for the Default-Activation-Locked Policy Bit\n"
|
|
+ " [2] value for the Commanded-Deactivation-Ignored Policy Bit\n"
|
|
+ " [1] value for the Deactivation-Locked Policy Bit\n"
|
|
+ " [0] value for the Activation-Locked Policy Bit"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_LED_PROP,
|
|
+ "usage: led prop <FRU-ID>"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_LED_CAP,
|
|
+ "usage: led cap <FRU-ID> <LED-ID"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_LED_GET,
|
|
+ "usage: led get <FRU-ID> <LED-ID",
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_LED_SET,
|
|
+ "usage: led set <FRU-ID> <LED-ID> <FUNCTION> <DURATION> <COLOR>\n"
|
|
+ " <FRU-ID>\n"
|
|
+ " <LED-ID> 0-0xFE: Specified LED\n"
|
|
+ " 0xFF: All LEDs under management control\n"
|
|
+ " <FUNCTION> 0: LED OFF override\n"
|
|
+ " 1 - 250: LED blinking override (off duration)\n"
|
|
+ " 251: LED Lamp Test\n"
|
|
+ " 252: LED restore to local control\n"
|
|
+ " 255: LED ON override\n"
|
|
+ " <DURATION> 1 - 127: LED Lamp Test / on duration\n"
|
|
+ " <COLOR> 1: BLUE\n"
|
|
+ " 2: RED\n"
|
|
+ " 3: GREEN\n"
|
|
+ " 4: AMBER\n"
|
|
+ " 5: ORANGE\n"
|
|
+ " 6: WHITE\n"
|
|
+ " 0xE: do not change\n"
|
|
+ " 0xF: use default color"
|
|
+ },
|
|
+ {
|
|
+ VITA_CMD_UNKNOWN,
|
|
+ "Unknown command"
|
|
+ },
|
|
+ { 0, NULL }
|
|
+};
|
|
+
|
|
+/* check if VITA 46.11 is supported */
|
|
+uint8_t
|
|
+vita_discover(struct ipmi_intf *intf)
|
|
+{
|
|
+ struct ipmi_rq req;
|
|
+ struct ipmi_rs *rsp;
|
|
+ unsigned char msg_data;
|
|
+ int vita_avail = 0;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_VSO_CAPABILITIES_CMD;
|
|
+ req.msg.data = &msg_data;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ msg_data = GROUP_EXT_VITA;
|
|
+
|
|
+ lprintf(LOG_INFO, "Running Get VSO Capabilities 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_ERR, "No valid response received");
|
|
+ } else if (rsp->ccode == 0xC1) {
|
|
+ lprintf(LOG_INFO, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ } else if (rsp->ccode == 0xCC) {
|
|
+ lprintf(LOG_INFO, "Invalid data field received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_INFO, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ } else if (rsp->data_len < 5) {
|
|
+ lprintf(LOG_INFO, "Invalid response length %d",
|
|
+ rsp->data_len);
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_INFO, "Invalid group extension %#x",
|
|
+ rsp->data[0]);
|
|
+ } else if ((rsp->data[3] & 0x03) != 0) {
|
|
+ lprintf(LOG_INFO, "Unknown VSO Standard %d",
|
|
+ (rsp->data[3] & 0x03));
|
|
+ } else if ((rsp->data[4] & 0x0F) != 1) {
|
|
+ lprintf(LOG_INFO, "Unknown VSO Specification Revision %d.%d",
|
|
+ (rsp->data[4] & 0x0F), (rsp->data[4] >> 4));
|
|
+ } else {
|
|
+ vita_avail = 1;
|
|
+ lprintf(LOG_INFO, "Discovered VITA 46.11 Revision %d.%d",
|
|
+ (rsp->data[4] & 0x0F), (rsp->data[4] >> 4));
|
|
+ }
|
|
+
|
|
+ return vita_avail;
|
|
+}
|
|
+
|
|
+uint8_t
|
|
+ipmi_vita_ipmb_address(struct ipmi_intf *intf)
|
|
+{
|
|
+ struct ipmi_rq req;
|
|
+ struct ipmi_rs *rsp;
|
|
+ unsigned char msg_data;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD;
|
|
+ req.msg.data = &msg_data;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ msg_data = GROUP_EXT_VITA;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received");
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ } else if (rsp->data_len < 7) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d",
|
|
+ rsp->data_len);
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x",
|
|
+ rsp->data[0]);
|
|
+ } else {
|
|
+ return rsp->data[2];
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_getaddr(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[2];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_FRU_ADDRESS_INFO_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 2;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ msg_data[1] = 0; /* default FRU ID */
|
|
+
|
|
+ if (argc > 0) {
|
|
+ /* validate and get FRU Device ID */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) {
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 7) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d",
|
|
+ rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x",
|
|
+ rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("Hardware Address : 0x%02x\n", rsp->data[1]);
|
|
+ printf("IPMB-0 Address : 0x%02x\n", rsp->data[2]);
|
|
+ printf("FRU ID : 0x%02x\n", rsp->data[4]);
|
|
+ printf("Site ID : 0x%02x\n", rsp->data[5]);
|
|
+ printf("Site Type : %s\n", val2str(rsp->data[6],
|
|
+ vita_site_types));
|
|
+ if (rsp->data_len > 8) {
|
|
+ printf("Channel 7 Address: 0x%02x\n", rsp->data[8]);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_vso_capabilities(struct ipmi_intf *intf)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data, tmp;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_VSO_CAPABILITIES_CMD;
|
|
+ req.msg.data = &msg_data;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ msg_data = GROUP_EXT_VITA; /* VITA identifier */
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 5) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("VSO Identifier : 0x%02x\n", rsp->data[0]);
|
|
+ printf("IPMC Identifier : 0x%02x\n", rsp->data[1]);
|
|
+ printf(" Tier %d\n", (rsp->data[1] & 0x03) + 1);
|
|
+ printf(" Layer %d\n", ((rsp->data[1] & 0x30) >> 4) + 1);
|
|
+
|
|
+ printf("IPMB Capabilities : 0x%02x\n", rsp->data[2]);
|
|
+
|
|
+ tmp = (rsp->data[2] & 0x30) >> 4;
|
|
+
|
|
+ printf(" Frequency %skHz\n",
|
|
+ tmp == 0 ? "100" : tmp == 1 ? "400" : "RESERVED");
|
|
+
|
|
+ tmp = rsp->data[2] & 3;
|
|
+
|
|
+ if (tmp == 1) {
|
|
+ printf(" 2 IPMB interfaces supported\n");
|
|
+ } else if (tmp == 0) {
|
|
+ printf(" 1 IPMB interface supported\n");
|
|
+ }
|
|
+
|
|
+ printf("VSO Standard : %s\n",
|
|
+ (rsp->data[3] & 0x3) == 0 ? "VITA 46.11" : "RESERVED");
|
|
+
|
|
+ printf("VSO Spec Revision : %d.%d\n", rsp->data[4] & 0xf,
|
|
+ rsp->data[4] >> 4);
|
|
+
|
|
+ printf("Max FRU Device ID : 0x%02x\n", rsp->data[5]);
|
|
+ printf("FRU Device ID : 0x%02x\n", rsp->data[6]);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_set_fru_activation(struct ipmi_intf *intf,
|
|
+ char **argv, unsigned char command)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[3];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_SET_FRU_ACTIVATION_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ msg_data[2] = command; /* command */
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 1) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("FRU has been successfully %s\n",
|
|
+ command ? "activated" : "deactivated");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_fru_state_policy_bits(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[2];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_FRU_STATE_POLICY_BITS_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 2;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 2) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("FRU State Policy Bits: %xh\n", rsp->data[1]);
|
|
+ printf(" Default-Activation-Locked Policy Bit is %d\n",
|
|
+ rsp->data[1] & 0x08 ? 1 : 0);
|
|
+ printf(" Commanded-Deactivation-Ignored Policy Bit is %d\n",
|
|
+ rsp->data[1] & 0x04 ? 1 : 0);
|
|
+ printf(" Deactivation-Locked Policy Bit is %d\n",
|
|
+ rsp->data[1] & 0x02 ? 1 : 0);
|
|
+ printf(" Activation-Locked Policy Bit is %d\n",
|
|
+ rsp->data[1] & 0x01);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_set_fru_state_policy_bits(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[4];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_SET_FRU_STATE_POLICY_BITS_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 4;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[1], &msg_data[2]) != 0) { /* bits mask */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[2], &msg_data[3]) != 0) { /* bits */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 1) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("FRU state policy bits have been updated\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_led_properties(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[2];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_FRU_LED_PROPERTIES_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 2;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 3) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("LED Count: %#x\n", rsp->data[2]);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_led_color_capabilities(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[3];
|
|
+ int i;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_LED_COLOR_CAPABILITIES_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 5) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("LED Color Capabilities: ");
|
|
+ for (i = 0; i < 8; i++) {
|
|
+ if (rsp->data[1] & (0x01 << i)) {
|
|
+ printf("%s, ", led_color_str[i]);
|
|
+ }
|
|
+ }
|
|
+ putchar('\n');
|
|
+
|
|
+ printf("Default LED Color in\n");
|
|
+ printf(" LOCAL control: %s\n", led_color_str[rsp->data[2]]);
|
|
+ printf(" OVERRIDE state: %s\n", led_color_str[rsp->data[3]]);
|
|
+
|
|
+ if (rsp->data_len == 5) {
|
|
+ printf("LED flags:\n");
|
|
+ if (rsp->data[4] & 2) {
|
|
+ printf(" [HW RESTRICT]\n");
|
|
+ }
|
|
+ if (rsp->data[4] & 1) {
|
|
+ printf(" [PAYLOAD PWR]\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_led_state(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[3];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_GET_FRU_LED_STATE_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 5
|
|
+ || ((rsp->data[1] & 0x2) && rsp->data_len < 8)
|
|
+ || ((rsp->data[1] & 0x4) && rsp->data_len < 9)) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("LED states: %x\t", rsp->data[1]);
|
|
+ if (rsp->data[1] & 0x1) {
|
|
+ printf("[LOCAL CONTROL] ");
|
|
+ }
|
|
+ if (rsp->data[1] & 0x2) {
|
|
+ printf("[OVERRIDE] ");
|
|
+ }
|
|
+ if (rsp->data[1] & 0x4) {
|
|
+ printf("[LAMPTEST] ");
|
|
+ }
|
|
+ if (rsp->data[1] & 0x8) {
|
|
+ printf("[HW RESTRICT] ");
|
|
+ }
|
|
+ putchar('\n');
|
|
+
|
|
+ if (rsp->data[1] & 1) {
|
|
+ printf(" Local Control function: %x\t", rsp->data[2]);
|
|
+ if (rsp->data[2] == 0x0) {
|
|
+ printf("[OFF]\n");
|
|
+ } else if (rsp->data[2] == 0xff) {
|
|
+ printf("[ON]\n");
|
|
+ } else {
|
|
+ printf("[BLINKING]\n");
|
|
+ }
|
|
+ printf(" Local Control On-Duration: %x\n", rsp->data[3]);
|
|
+ printf(" Local Control Color: %x\t[%s]\n",
|
|
+ rsp->data[4], led_color_str[rsp->data[4] & 7]);
|
|
+ }
|
|
+
|
|
+ /* override state or lamp test */
|
|
+ if (rsp->data[1] & 0x06) {
|
|
+ printf(" Override function: %x\t", rsp->data[5]);
|
|
+ if (rsp->data[5] == 0x0) {
|
|
+ printf("[OFF]\n");
|
|
+ } else if (rsp->data[5] == 0xff) {
|
|
+ printf("[ON]\n");
|
|
+ } else {
|
|
+ printf("[BLINKING]\n");
|
|
+ }
|
|
+ printf(" Override On-Duration: %x\n", rsp->data[6]);
|
|
+ printf(" Override Color: %x\t[%s]\n",
|
|
+ rsp->data[7], led_color_str[rsp->data[7] & 7]);
|
|
+ if (rsp->data[1] == 0x04) {
|
|
+ printf(" Lamp test duration: %x\n", rsp->data[8]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_set_led_state(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[6];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_SET_FRU_LED_STATE_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 6;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[1], &msg_data[2]) != 0) { /* LED-ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[2], &msg_data[3]) != 0) { /* LED function */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[3], &msg_data[4]) != 0) { /* LED on duration */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[4], &msg_data[5]) != 0) { /* LED color */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 1) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("LED state has been updated\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_fru_control(struct ipmi_intf *intf, char **argv)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char msg_data[3];
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = VITA_FRU_CONTROL_CMD;
|
|
+ req.msg.data = msg_data;
|
|
+ req.msg.data_len = 3;
|
|
+
|
|
+ msg_data[0] = GROUP_EXT_VITA; /* VITA identifier */
|
|
+ if (is_fru_id(argv[0], &msg_data[1]) != 0) { /* FRU ID */
|
|
+ return -1;
|
|
+ }
|
|
+ if (str2uchar(argv[1], &msg_data[2]) != 0) { /* control option */
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("FRU Device Id: %d FRU Control Option: %s\n", msg_data[1],
|
|
+ val2str(msg_data[2], picmg_frucontrol_vals));
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "No valid response received.");
|
|
+ return -1;
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Invalid completion code received: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return -1;
|
|
+ } else if (rsp->data_len < 1) {
|
|
+ lprintf(LOG_ERR, "Invalid response length %d", rsp->data_len);
|
|
+ return -1;
|
|
+ } else if (rsp->data[0] != GROUP_EXT_VITA) {
|
|
+ lprintf(LOG_ERR, "Invalid group extension %#x", rsp->data[0]);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ printf("FRU Control: ok\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_vita_get_cmd(int argc, char **argv)
|
|
+{
|
|
+ if (argc < 1 || !strncmp(argv[0], "help", 4)) {
|
|
+ return VITA_CMD_HELP;
|
|
+ }
|
|
+
|
|
+ /* Get VSO Properties */
|
|
+ if (!strncmp(argv[0], "properties", 10)) {
|
|
+ return VITA_CMD_PROPERTIES;
|
|
+ }
|
|
+
|
|
+ /* FRU Control command */
|
|
+ if (!strncmp(argv[0], "frucontrol", 10)) {
|
|
+ return VITA_CMD_FRUCONTROL;
|
|
+ }
|
|
+
|
|
+ /* Get FRU Address Info command */
|
|
+ if (!strncmp(argv[0], "addrinfo", 8)) {
|
|
+ return VITA_CMD_ADDRINFO;
|
|
+ }
|
|
+
|
|
+ /* Set FRU Activation (activate) command */
|
|
+ if (!strncmp(argv[0], "activate", 8)) {
|
|
+ return VITA_CMD_ACTIVATE;
|
|
+ }
|
|
+
|
|
+ /* Set FRU Activation (deactivate) command */
|
|
+ if (!strncmp(argv[0], "deactivate", 10)) {
|
|
+ return VITA_CMD_DEACTIVATE;
|
|
+ }
|
|
+
|
|
+ /* FRU State Policy Bits commands */
|
|
+ if (!strncmp(argv[0], "policy", 6)) {
|
|
+ if (argc < 2) {
|
|
+ return VITA_CMD_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ /* Get FRU State Policy Bits command */
|
|
+ if (!strncmp(argv[1], "get", 3)) {
|
|
+ return VITA_CMD_POLICY_GET;
|
|
+ }
|
|
+
|
|
+ /* Set FRU State Policy Bits command */
|
|
+ if (!strncmp(argv[1], "set", 3)) {
|
|
+ return VITA_CMD_POLICY_SET;
|
|
+ }
|
|
+
|
|
+ /* unknown command */
|
|
+ return VITA_CMD_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ /* FRU LED commands */
|
|
+ if (!strncmp(argv[0], "led", 3)) {
|
|
+ if (argc < 2) {
|
|
+ return VITA_CMD_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ /* FRU LED Get Properties */
|
|
+ if (!strncmp(argv[1], "prop", 4)) {
|
|
+ return VITA_CMD_LED_PROP;
|
|
+ }
|
|
+
|
|
+ /* FRU LED Get Capabilities */
|
|
+ if (!strncmp(argv[1], "cap", 3)) {
|
|
+ return VITA_CMD_LED_CAP;
|
|
+ }
|
|
+
|
|
+ /* FRU LED Get State */
|
|
+ if (!strncmp(argv[1], "get", 3)) {
|
|
+ return VITA_CMD_LED_GET;
|
|
+ }
|
|
+
|
|
+ /* FRU LED Set State */
|
|
+ if (!strncmp(argv[1], "set", 3)) {
|
|
+ return VITA_CMD_LED_SET;
|
|
+ }
|
|
+
|
|
+ /* unknown command */
|
|
+ return VITA_CMD_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ /* unknown command */
|
|
+ return VITA_CMD_UNKNOWN;
|
|
+}
|
|
+
|
|
+int
|
|
+ipmi_vita_main (struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ int rc = -1, show_help = 0;
|
|
+ int cmd = ipmi_vita_get_cmd(argc, argv);
|
|
+
|
|
+ switch (cmd) {
|
|
+ case VITA_CMD_HELP:
|
|
+ cmd = ipmi_vita_get_cmd(argc - 1, &argv[1]);
|
|
+ show_help = 1;
|
|
+ rc = 0;
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_PROPERTIES:
|
|
+ rc = ipmi_vita_get_vso_capabilities(intf);
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_FRUCONTROL:
|
|
+ if (argc > 2) {
|
|
+ rc = ipmi_vita_fru_control(intf, &argv[1]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_ADDRINFO:
|
|
+ rc = ipmi_vita_getaddr(intf, argc - 1, &argv[1]);
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_ACTIVATE:
|
|
+ if (argc > 1) {
|
|
+ rc = ipmi_vita_set_fru_activation(intf, &argv[1], 1);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_DEACTIVATE:
|
|
+ if (argc > 1) {
|
|
+ rc = ipmi_vita_set_fru_activation(intf, &argv[1], 0);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_POLICY_GET:
|
|
+ if (argc > 2) {
|
|
+ rc = ipmi_vita_get_fru_state_policy_bits(intf,
|
|
+ &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_POLICY_SET:
|
|
+ if (argc > 4) {
|
|
+ rc = ipmi_vita_set_fru_state_policy_bits(intf,
|
|
+ &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_LED_PROP:
|
|
+ if (argc > 2) {
|
|
+ rc = ipmi_vita_get_led_properties(intf, &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_LED_CAP:
|
|
+ if (argc > 3) {
|
|
+ rc = ipmi_vita_get_led_color_capabilities(intf,
|
|
+ &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_LED_GET:
|
|
+ if (argc > 3) {
|
|
+ rc = ipmi_vita_get_led_state(intf, &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case VITA_CMD_LED_SET:
|
|
+ if (argc > 6) {
|
|
+ rc = ipmi_vita_set_led_state(intf, &argv[2]);
|
|
+ } else {
|
|
+ show_help = 1;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ lprintf(LOG_NOTICE, "Unknown command");
|
|
+ cmd = VITA_CMD_HELP;
|
|
+ show_help = 1;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (show_help) {
|
|
+ lprintf(LOG_NOTICE, "%s", val2str(cmd, vita_help_strings));
|
|
+ }
|
|
+
|
|
+ return rc;
|
|
+}
|
|
diff --git a/src/ipmievd.c b/src/ipmievd.c
|
|
index f940579..cc1ca0f 100644
|
|
--- a/src/ipmievd.c
|
|
+++ b/src/ipmievd.c
|
|
@@ -29,6 +29,7 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _XOPEN_SOURCE 700
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
@@ -122,13 +123,13 @@ static int openipmi_setup(struct ipmi_event_intf * eintf);
|
|
static int openipmi_wait(struct ipmi_event_intf * eintf);
|
|
static int openipmi_read(struct ipmi_event_intf * eintf);
|
|
static struct ipmi_event_intf openipmi_event_intf = {
|
|
- name: "open",
|
|
- desc: "OpenIPMI asyncronous notification of events",
|
|
- prefix: "",
|
|
- setup: openipmi_setup,
|
|
- wait: openipmi_wait,
|
|
- read: openipmi_read,
|
|
- log: log_event,
|
|
+ .name = "open",
|
|
+ .desc = "OpenIPMI asyncronous notification of events",
|
|
+ .prefix = "",
|
|
+ .setup = openipmi_setup,
|
|
+ .wait = openipmi_wait,
|
|
+ .read = openipmi_read,
|
|
+ .log = log_event,
|
|
};
|
|
#endif
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
@@ -139,13 +140,13 @@ static int selwatch_wait(struct ipmi_event_intf * eintf);
|
|
static int selwatch_read(struct ipmi_event_intf * eintf);
|
|
static int selwatch_check(struct ipmi_event_intf * eintf);
|
|
static struct ipmi_event_intf selwatch_event_intf = {
|
|
- name: "sel",
|
|
- desc: "Poll SEL for notification of events",
|
|
- setup: selwatch_setup,
|
|
- wait: selwatch_wait,
|
|
- read: selwatch_read,
|
|
- check: selwatch_check,
|
|
- log: log_event,
|
|
+ .name = "sel",
|
|
+ .desc = "Poll SEL for notification of events",
|
|
+ .setup = selwatch_setup,
|
|
+ .wait = selwatch_wait,
|
|
+ .read = selwatch_read,
|
|
+ .check = selwatch_check,
|
|
+ .log = log_event,
|
|
};
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
@@ -283,7 +284,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
eintf->prefix,
|
|
type,
|
|
sdr->record.full->id_string,
|
|
- desc ? : "",
|
|
+ desc ? desc : "",
|
|
(evt->sel_type.standard_type.event_dir
|
|
? "Deasserted" : "Asserted"),
|
|
(trigger_reading==(int)trigger_reading) ? 0 : 2,
|
|
@@ -303,7 +304,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
*/
|
|
lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
|
|
eintf->prefix, type,
|
|
- sdr->record.full->id_string, desc ? : "",
|
|
+ sdr->record.full->id_string, desc ? desc : "",
|
|
(evt->sel_type.standard_type.event_dir
|
|
? "Deasserted" : "Asserted"));
|
|
if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
|
|
@@ -316,7 +317,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
*/
|
|
lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
|
|
eintf->prefix, type,
|
|
- sdr->record.full->id_string, desc ? : "",
|
|
+ sdr->record.full->id_string, desc ? desc : "",
|
|
(evt->sel_type.standard_type.event_dir
|
|
? "Deasserted" : "Asserted"));
|
|
}
|
|
@@ -325,7 +326,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
case SDR_RECORD_TYPE_COMPACT_SENSOR:
|
|
lprintf(LOG_NOTICE, "%s%s sensor %s - %s %s",
|
|
eintf->prefix, type,
|
|
- sdr->record.compact->id_string, desc ? : "",
|
|
+ sdr->record.compact->id_string, desc ? desc : "",
|
|
(evt->sel_type.standard_type.event_dir
|
|
? "Deasserted" : "Asserted"));
|
|
break;
|
|
@@ -333,7 +334,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
|
|
default:
|
|
lprintf(LOG_NOTICE, "%s%s sensor - %s",
|
|
eintf->prefix, type,
|
|
- evt->sel_type.standard_type.sensor_num, desc ? : "");
|
|
+ evt->sel_type.standard_type.sensor_num, desc ? desc : "");
|
|
break;
|
|
}
|
|
|
|
@@ -703,7 +704,6 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv)
|
|
|
|
memset(pidfile, 0, 64);
|
|
sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum);
|
|
- lprintf(LOG_NOTICE, "ipmievd: using pidfile %s", pidfile);
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
if (strncasecmp(argv[i], "help", 4) == 0) {
|
|
@@ -738,6 +738,8 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv)
|
|
}
|
|
}
|
|
|
|
+ lprintf(LOG_DEBUG, "ipmievd: using pidfile %s", pidfile);
|
|
+
|
|
/*
|
|
* We need to open interface before forking daemon
|
|
* so error messages are not lost to syslog and
|
|
@@ -831,8 +833,8 @@ ipmievd_sel_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
|
if (intf->session != NULL) {
|
|
snprintf(eintf->prefix,
|
|
- strlen((const char *)intf->session->hostname) + 3,
|
|
- "%s: ", intf->session->hostname);
|
|
+ strlen((const char *)intf->ssn_params.hostname) + 3,
|
|
+ "%s: ", intf->ssn_params.hostname);
|
|
}
|
|
|
|
return ipmievd_main(eintf, argc, argv);
|
|
diff --git a/src/ipmishell.c b/src/ipmishell.c
|
|
index 4eebcd8..6cfcbe8 100644
|
|
--- a/src/ipmishell.c
|
|
+++ b/src/ipmishell.c
|
|
@@ -301,7 +301,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return (-1);
|
|
}
|
|
printf("Set session hostname to %s\n",
|
|
- intf->session->hostname);
|
|
+ intf->ssn_params.hostname);
|
|
}
|
|
else if (strncmp(argv[0], "user", 4) == 0 ||
|
|
strncmp(argv[0], "username", 8) == 0) {
|
|
@@ -311,7 +311,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return (-1);
|
|
}
|
|
printf("Set session username to %s\n",
|
|
- intf->session->username);
|
|
+ intf->ssn_params.username);
|
|
}
|
|
else if (strncmp(argv[0], "pass", 4) == 0 ||
|
|
strncmp(argv[0], "password", 8) == 0) {
|
|
@@ -336,7 +336,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return (-1);
|
|
}
|
|
printf("Set session authtype to %s\n",
|
|
- val2str(intf->session->authtype_set,
|
|
+ val2str(intf->ssn_params.authtype_set,
|
|
ipmi_authtype_session_vals));
|
|
}
|
|
else if (strncmp(argv[0], "privlvl", 7) == 0) {
|
|
@@ -354,7 +354,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
return (-1);
|
|
}
|
|
printf("Set session privilege level to %s\n",
|
|
- val2str(intf->session->privlvl,
|
|
+ val2str(intf->ssn_params.privlvl,
|
|
ipmi_privlvl_vals));
|
|
}
|
|
else if (strncmp(argv[0], "port", 4) == 0) {
|
|
@@ -369,7 +369,7 @@ int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
lprintf(LOG_ERR, "Failed to set session port.");
|
|
return (-1);
|
|
}
|
|
- printf("Set session port to %d\n", intf->session->port);
|
|
+ printf("Set session port to %d\n", intf->ssn_params.port);
|
|
}
|
|
else if (strncmp(argv[0], "localaddr", 9) == 0) {
|
|
uint8_t my_addr = 0;
|
|
@@ -467,6 +467,10 @@ int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
__argv[__argc++] = strdup(tok);
|
|
if (__argv[__argc-1] == NULL) {
|
|
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ if (fp) {
|
|
+ fclose(fp);
|
|
+ fp = NULL;
|
|
+ }
|
|
return -1;
|
|
}
|
|
tmp = __argv[__argc-1];
|
|
diff --git a/src/ipmitool.c b/src/ipmitool.c
|
|
index 6230e5c..164fd44 100644
|
|
--- a/src/ipmitool.c
|
|
+++ b/src/ipmitool.c
|
|
@@ -65,6 +65,7 @@
|
|
#include <ipmitool/ipmi_ekanalyzer.h>
|
|
#include <ipmitool/ipmi_ime.h>
|
|
#include <ipmitool/ipmi_dcmi.h>
|
|
+#include <ipmitool/ipmi_vita.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
@@ -103,7 +104,8 @@ struct ipmi_cmd ipmitool_cmd_list[] = {
|
|
{ ipmi_user_main, "user", "Configure Management Controller users" },
|
|
{ ipmi_channel_main, "channel", "Configure Management Controller channels" },
|
|
{ ipmi_session_main, "session", "Print session information" },
|
|
- { ipmi_dcmi_main, "dcmi", "Data Center Management Interface"},
|
|
+ { ipmi_dcmi_main, "dcmi", "Data Center Management Interface"},
|
|
+ { ipmi_nm_main, "nm", "Node Manager Interface"},
|
|
{ ipmi_sunoem_main, "sunoem", "OEM Commands for Sun servers" },
|
|
{ ipmi_kontronoem_main, "kontronoem", "OEM Commands for Kontron devices"},
|
|
{ ipmi_picmg_main, "picmg", "Run a PICMG/ATCA extended cmd"},
|
|
@@ -119,6 +121,7 @@ struct ipmi_cmd ipmitool_cmd_list[] = {
|
|
{ ipmi_hpmfwupg_main,"hpm", "Update HPM components using PICMG HPM.1 file"},
|
|
{ ipmi_ekanalyzer_main,"ekanalyzer", "run FRU-Ekeying analyzer using FRU files"},
|
|
{ ipmi_ime_main, "ime", "Update Intel Manageability Engine Firmware"},
|
|
+ { ipmi_vita_main, "vita", "Run a VITA 46.11 extended cmd"},
|
|
{ NULL },
|
|
};
|
|
|
|
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
|
|
index 19b5f11..a2c48ff 100644
|
|
--- a/src/plugins/Makefile.am
|
|
+++ b/src/plugins/Makefile.am
|
|
@@ -32,8 +32,8 @@ MAINTAINERCLEANFILES = Makefile.in
|
|
|
|
INCLUDES = -I$(top_srcdir)/include
|
|
|
|
-SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@
|
|
-DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy
|
|
+SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@
|
|
+DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb
|
|
|
|
noinst_LTLIBRARIES = libintf.la
|
|
libintf_la_SOURCES = ipmi_intf.c
|
|
diff --git a/src/plugins/dummy/dummy.c b/src/plugins/dummy/dummy.c
|
|
index eb2d086..8bfc4cf 100644
|
|
--- a/src/plugins/dummy/dummy.c
|
|
+++ b/src/plugins/dummy/dummy.c
|
|
@@ -117,7 +117,7 @@ data_write(int fd, void *data_ptr, int data_len)
|
|
/* TODO - add poll() */
|
|
data_written = write(fd, data_ptr, data_len);
|
|
errno_save = errno;
|
|
- if (data_read > 0) {
|
|
+ if (data_written > 0) {
|
|
data_total+= data_written;
|
|
}
|
|
if (errno_save != 0) {
|
|
@@ -149,9 +149,6 @@ static void
|
|
ipmi_dummyipmi_close(struct ipmi_intf *intf)
|
|
{
|
|
struct dummy_rq req;
|
|
- int data_total = 0;
|
|
- int data_written = 0;
|
|
- int try = 0;
|
|
if (intf->fd < 0) {
|
|
return;
|
|
}
|
|
@@ -245,7 +242,7 @@ ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
|
return NULL;
|
|
}
|
|
}
|
|
-
|
|
+
|
|
memset(&rsp_dummy, 0, sizeof(rsp_dummy));
|
|
if (data_read(intf->fd, &rsp_dummy, sizeof(struct dummy_rs)) != 0) {
|
|
return NULL;
|
|
@@ -276,11 +273,11 @@ ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
|
}
|
|
|
|
struct ipmi_intf ipmi_dummy_intf = {
|
|
- name: "dummy",
|
|
- desc: "Linux DummyIPMI Interface",
|
|
- open: ipmi_dummyipmi_open,
|
|
- close: ipmi_dummyipmi_close,
|
|
- sendrecv: ipmi_dummyipmi_send_cmd,
|
|
- my_addr: IPMI_BMC_SLAVE_ADDR,
|
|
- target_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+ .name = "dummy",
|
|
+ .desc = "Linux DummyIPMI Interface",
|
|
+ .open = ipmi_dummyipmi_open,
|
|
+ .close = ipmi_dummyipmi_close,
|
|
+ .sendrecv = ipmi_dummyipmi_send_cmd,
|
|
+ .my_addr = IPMI_BMC_SLAVE_ADDR,
|
|
+ .target_addr = IPMI_BMC_SLAVE_ADDR,
|
|
};
|
|
diff --git a/src/plugins/free/free.c b/src/plugins/free/free.c
|
|
index f89925d..56c8157 100644
|
|
--- a/src/plugins/free/free.c
|
|
+++ b/src/plugins/free/free.c
|
|
@@ -203,12 +203,12 @@ static void ipmi_free_close(struct ipmi_intf * intf)
|
|
|
|
static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
{
|
|
- u_int8_t lun = req->msg.lun;
|
|
- u_int8_t cmd = req->msg.cmd;
|
|
- u_int8_t netfn = req->msg.netfn;
|
|
- u_int8_t rq_buf[IPMI_BUF_SIZE];
|
|
- u_int8_t rs_buf[IPMI_BUF_SIZE];
|
|
- u_int32_t rs_buf_len = IPMI_BUF_SIZE;
|
|
+ uint8_t lun = req->msg.lun;
|
|
+ uint8_t cmd = req->msg.cmd;
|
|
+ uint8_t netfn = req->msg.netfn;
|
|
+ uint8_t rq_buf[IPMI_BUF_SIZE];
|
|
+ uint8_t rs_buf[IPMI_BUF_SIZE];
|
|
+ uint32_t rs_buf_len = IPMI_BUF_SIZE;
|
|
int32_t rs_len;
|
|
|
|
static struct ipmi_rs rsp;
|
|
diff --git a/src/plugins/imb/imb.c b/src/plugins/imb/imb.c
|
|
index cb97e81..0044159 100644
|
|
--- a/src/plugins/imb/imb.c
|
|
+++ b/src/plugins/imb/imb.c
|
|
@@ -121,11 +121,11 @@ static struct ipmi_rs * ipmi_imb_send_cmd(struct ipmi_intf * intf, struct ipmi_r
|
|
}
|
|
|
|
struct ipmi_intf ipmi_imb_intf = {
|
|
- name: "imb",
|
|
- desc: "Intel IMB Interface",
|
|
- open: ipmi_imb_open,
|
|
- close: ipmi_imb_close,
|
|
- sendrecv: ipmi_imb_send_cmd,
|
|
- target_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+ .name = "imb",
|
|
+ .desc = "Intel IMB Interface",
|
|
+ .open = ipmi_imb_open,
|
|
+ .close = ipmi_imb_close,
|
|
+ .sendrecv = ipmi_imb_send_cmd,
|
|
+ .target_addr = IPMI_BMC_SLAVE_ADDR,
|
|
};
|
|
|
|
diff --git a/src/plugins/imb/imbapi.c b/src/plugins/imb/imbapi.c
|
|
index 37d3abe..899c47a 100644
|
|
--- a/src/plugins/imb/imbapi.c
|
|
+++ b/src/plugins/imb/imbapi.c
|
|
@@ -97,6 +97,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#include <string.h>
|
|
#endif
|
|
#include "imbapi.h"
|
|
+#include <asm/socket.h>
|
|
|
|
#ifdef SCO_UW
|
|
#define NO_MACRO_ARGS 1
|
|
@@ -104,7 +105,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#define IMB_DEVICE "/dev/instru/mismic"
|
|
#else
|
|
#define IMB_DEVICE "/dev/imb"
|
|
-#define PAGESIZE EXEC_PAGESIZE
|
|
+#ifndef PAGESIZE
|
|
+# define PAGESIZE EXEC_PAGESIZE
|
|
+#endif
|
|
#endif
|
|
|
|
/*Just to make the DEBUG code cleaner.*/
|
|
@@ -1981,7 +1984,7 @@ MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress )
|
|
unsigned int length = addressLength;
|
|
off_t startpAddress = (off_t)startAddress;
|
|
unsigned int diff;
|
|
- caddr_t startvAddress;
|
|
+ char *startvAddress;
|
|
|
|
if ((startAddress == 0) || (addressLength <= 0))
|
|
return ACCESN_ERROR;
|
|
@@ -2000,13 +2003,13 @@ MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress )
|
|
startpAddress -= diff;
|
|
length += diff;
|
|
|
|
- if ( (startvAddress = mmap( (caddr_t)0,
|
|
+ if ( (startvAddress = mmap(0,
|
|
length,
|
|
PROT_READ,
|
|
MAP_SHARED,
|
|
fd,
|
|
startpAddress
|
|
- ) ) == (caddr_t)-1)
|
|
+ ) ) == MAP_FAILED)
|
|
{
|
|
char buf[128];
|
|
|
|
diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c
|
|
index a84237e..6bb7008 100644
|
|
--- a/src/plugins/ipmi_intf.c
|
|
+++ b/src/plugins/ipmi_intf.c
|
|
@@ -29,6 +29,8 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _XOPEN_SOURCE 700
|
|
+#define _GNU_SOURCE 1
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
@@ -83,6 +85,9 @@ extern struct ipmi_intf ipmi_serial_bm_intf;
|
|
#ifdef IPMI_INTF_DUMMY
|
|
extern struct ipmi_intf ipmi_dummy_intf;
|
|
#endif
|
|
+#ifdef IPMI_INTF_USB
|
|
+extern struct ipmi_intf ipmi_usb_intf;
|
|
+#endif
|
|
|
|
struct ipmi_intf * ipmi_intf_table[] = {
|
|
#ifdef IPMI_INTF_OPEN
|
|
@@ -113,6 +118,9 @@ struct ipmi_intf * ipmi_intf_table[] = {
|
|
#ifdef IPMI_INTF_DUMMY
|
|
&ipmi_dummy_intf,
|
|
#endif
|
|
+#ifdef IPMI_INTF_USB
|
|
+ &ipmi_usb_intf,
|
|
+#endif
|
|
NULL
|
|
};
|
|
|
|
@@ -194,139 +202,106 @@ struct ipmi_intf * ipmi_intf_load(char * name)
|
|
void
|
|
ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
|
|
{
|
|
- if (intf->session == NULL || hostname == NULL) {
|
|
- return;
|
|
+ if (intf->ssn_params.hostname != NULL) {
|
|
+ free(intf->ssn_params.hostname);
|
|
+ intf->ssn_params.hostname = NULL;
|
|
}
|
|
- if (intf->session->hostname != NULL) {
|
|
- free(intf->session->hostname);
|
|
- intf->session->hostname = NULL;
|
|
+ if (hostname == NULL) {
|
|
+ return;
|
|
}
|
|
- intf->session->hostname = strdup(hostname);
|
|
+ intf->ssn_params.hostname = strdup(hostname);
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- memset(intf->session->username, 0, 17);
|
|
+ memset(intf->ssn_params.username, 0, 17);
|
|
|
|
if (username == NULL)
|
|
return;
|
|
|
|
- memcpy(intf->session->username, username, __min(strlen(username), 16));
|
|
+ memcpy(intf->ssn_params.username, username, __min(strlen(username), 16));
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
|
+ memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
|
|
|
if (password == NULL) {
|
|
- intf->session->password = 0;
|
|
+ intf->ssn_params.password = 0;
|
|
return;
|
|
}
|
|
|
|
- intf->session->password = 1;
|
|
- memcpy(intf->session->authcode, password,
|
|
+ intf->ssn_params.password = 1;
|
|
+ memcpy(intf->ssn_params.authcode_set, password,
|
|
__min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->privlvl = level;
|
|
+ intf->ssn_params.privlvl = level;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->v2_data.lookupbit = lookupbit;
|
|
+ intf->ssn_params.lookupbit = lookupbit;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->cipher_suite_id = cipher_suite_id;
|
|
+ intf->ssn_params.cipher_suite_id = cipher_suite_id;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->sol_escape_char = sol_escape_char;
|
|
+ intf->ssn_params.sol_escape_char = sol_escape_char;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
|
|
+ memset(intf->ssn_params.kg, 0, IPMI_KG_BUFFER_SIZE);
|
|
|
|
if (kgkey == NULL)
|
|
return;
|
|
|
|
- memcpy(intf->session->v2_data.kg, kgkey,
|
|
+ memcpy(intf->ssn_params.kg, kgkey,
|
|
__min(strlen(kgkey), IPMI_KG_BUFFER_SIZE));
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->port = port;
|
|
+ intf->ssn_params.port = port;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
/* clear password field if authtype NONE specified */
|
|
if (authtype == IPMI_SESSION_AUTHTYPE_NONE) {
|
|
- memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
|
- intf->session->password = 0;
|
|
+ memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
|
|
+ intf->ssn_params.password = 0;
|
|
}
|
|
|
|
- intf->session->authtype_set = authtype;
|
|
+ intf->ssn_params.authtype_set = authtype;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->timeout = timeout;
|
|
+ intf->ssn_params.timeout = timeout;
|
|
}
|
|
|
|
void
|
|
ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry)
|
|
{
|
|
- if (intf->session == NULL)
|
|
- return;
|
|
-
|
|
- intf->session->retry = retry;
|
|
+ intf->ssn_params.retry = retry;
|
|
}
|
|
|
|
void
|
|
@@ -335,10 +310,7 @@ ipmi_intf_session_cleanup(struct ipmi_intf *intf)
|
|
if (intf->session == NULL) {
|
|
return;
|
|
}
|
|
- if (intf->session->hostname != NULL) {
|
|
- free(intf->session->hostname);
|
|
- intf->session->hostname = NULL;
|
|
- }
|
|
+
|
|
free(intf->session);
|
|
intf->session = NULL;
|
|
}
|
|
@@ -347,27 +319,27 @@ void
|
|
ipmi_cleanup(struct ipmi_intf * intf)
|
|
{
|
|
ipmi_sdr_list_empty(intf);
|
|
+ ipmi_intf_session_set_hostname(intf, NULL);
|
|
}
|
|
|
|
#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
|
int
|
|
ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
{
|
|
- struct ipmi_session *session;
|
|
+ struct ipmi_session_params *params;
|
|
|
|
struct sockaddr_storage addr;
|
|
struct addrinfo hints;
|
|
struct addrinfo *rp0 = NULL, *rp;
|
|
char service[NI_MAXSERV];
|
|
- int rc;
|
|
|
|
- if (!intf || intf->session == NULL) {
|
|
+ if (!intf) {
|
|
return -1;
|
|
}
|
|
|
|
- session = intf->session;
|
|
+ params = &intf->ssn_params;
|
|
|
|
- if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
|
|
+ if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
|
|
lprintf(LOG_ERR, "No hostname specified!");
|
|
return -1;
|
|
}
|
|
@@ -375,7 +347,7 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
/* open port to BMC */
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
- sprintf(service, "%d", session->port);
|
|
+ sprintf(service, "%d", params->port);
|
|
/* Obtain address(es) matching host/port */
|
|
memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
|
@@ -383,19 +355,18 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */
|
|
hints.ai_protocol = IPPROTO_UDP; /* */
|
|
|
|
- if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) {
|
|
+ if (getaddrinfo(params->hostname, service, &hints, &rp0) != 0) {
|
|
lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
- session->hostname);
|
|
+ params->hostname);
|
|
return -1;
|
|
}
|
|
|
|
/* getaddrinfo() returns a list of address structures.
|
|
* Try each address until we successfully connect(2).
|
|
* If socket(2) (or connect(2)) fails, we (close the socket
|
|
- * and) try the next address.
|
|
+ * and) try the next address.
|
|
*/
|
|
|
|
- session->ai_family = AF_UNSPEC;
|
|
for (rp = rp0; rp != NULL; rp = rp->ai_next) {
|
|
/* We are only interested in IPv4 and IPv6 */
|
|
if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
|
|
@@ -409,9 +380,7 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
|
|
if (rp->ai_family == AF_INET) {
|
|
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
- memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
- session->addrlen = rp->ai_addrlen;
|
|
- session->ai_family = rp->ai_family;
|
|
+ hints.ai_family = rp->ai_family;
|
|
break; /* Success */
|
|
}
|
|
} else if (rp->ai_family == AF_INET6) {
|
|
@@ -423,14 +392,12 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
if (addr6->sin6_scope_id != 0) {
|
|
len = sizeof(struct sockaddr_in6);
|
|
if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
|
- lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
|
|
- hbuf,
|
|
+ lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
|
|
+ hbuf,
|
|
addr6->sin6_scope_id);
|
|
}
|
|
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
- memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
- session->addrlen = rp->ai_addrlen;
|
|
- session->ai_family = rp->ai_family;
|
|
+ hints.ai_family = rp->ai_family;
|
|
break; /* Success */
|
|
}
|
|
} else {
|
|
@@ -440,7 +407,7 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
|
|
if (getifaddrs(&ifaddrs) < 0) {
|
|
lprintf(LOG_ERR, "Interface address lookup for %s failed",
|
|
- session->hostname);
|
|
+ params->hostname);
|
|
break;
|
|
}
|
|
|
|
@@ -461,44 +428,42 @@ ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
}
|
|
len = sizeof(struct sockaddr_in6);
|
|
if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
|
- lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
|
|
- ifa->ifa_name != NULL ? ifa->ifa_name : "???",
|
|
- hbuf,
|
|
+ lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
|
|
+ ifa->ifa_name != NULL ? ifa->ifa_name : "???",
|
|
+ hbuf,
|
|
tmp6->sin6_scope_id);
|
|
}
|
|
|
|
if (tmp6->sin6_scope_id != 0) {
|
|
addr6->sin6_scope_id = tmp6->sin6_scope_id;
|
|
} else {
|
|
- /*
|
|
- * No scope information in interface address information
|
|
+ /*
|
|
+ * No scope information in interface address information
|
|
* On some OS'es, getifaddrs() is returning out the 'kernel' representation
|
|
* of scoped addresses which stores the scope in the 3rd and 4th
|
|
* byte. See also this page:
|
|
* http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
|
|
*/
|
|
if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
|
|
- && (tmp6->sin6_addr.s6_addr16[1] != 0)) {
|
|
- addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]);
|
|
+ && (tmp6->sin6_addr.s6_addr[1] != 0)) {
|
|
+ addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr[1]);
|
|
}
|
|
}
|
|
|
|
/* OK, now try to connect with the scope id from this interface address */
|
|
if (addr6->sin6_scope_id != 0) {
|
|
if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
- memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
- session->addrlen = rp->ai_addrlen;
|
|
- session->ai_family = rp->ai_family;
|
|
+ hints.ai_family = rp->ai_family;
|
|
lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
|
|
break; /* Success */
|
|
}
|
|
- }
|
|
+ }
|
|
}
|
|
}
|
|
freeifaddrs(ifaddrs);
|
|
}
|
|
}
|
|
- if (session->ai_family != AF_UNSPEC) {
|
|
+ if (hints.ai_family != AF_UNSPEC) {
|
|
break;
|
|
}
|
|
close(intf->fd);
|
|
diff --git a/src/plugins/lan/lan.c b/src/plugins/lan/lan.c
|
|
index dd90706..14730d3 100644
|
|
--- a/src/plugins/lan/lan.c
|
|
+++ b/src/plugins/lan/lan.c
|
|
@@ -29,12 +29,15 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
+#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/select.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
@@ -100,19 +103,19 @@ static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size
|
|
static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
|
|
|
|
struct ipmi_intf ipmi_lan_intf = {
|
|
- name: "lan",
|
|
- desc: "IPMI v1.5 LAN Interface",
|
|
- setup: ipmi_lan_setup,
|
|
- open: ipmi_lan_open,
|
|
- close: ipmi_lan_close,
|
|
- sendrecv: ipmi_lan_send_cmd,
|
|
- sendrsp: ipmi_lan_send_rsp,
|
|
- recv_sol: ipmi_lan_recv_sol,
|
|
- send_sol: ipmi_lan_send_sol,
|
|
- keepalive: ipmi_lan_keepalive,
|
|
- set_max_request_data_size: ipmi_lan_set_max_rq_data_size,
|
|
- set_max_response_data_size: ipmi_lan_set_max_rp_data_size,
|
|
- target_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+ .name = "lan",
|
|
+ .desc = "IPMI v1.5 LAN Interface",
|
|
+ .setup = ipmi_lan_setup,
|
|
+ .open = ipmi_lan_open,
|
|
+ .close = ipmi_lan_close,
|
|
+ .sendrecv = ipmi_lan_send_cmd,
|
|
+ .sendrsp = ipmi_lan_send_rsp,
|
|
+ .recv_sol = ipmi_lan_recv_sol,
|
|
+ .send_sol = ipmi_lan_send_sol,
|
|
+ .keepalive = ipmi_lan_keepalive,
|
|
+ .set_max_request_data_size = ipmi_lan_set_max_rq_data_size,
|
|
+ .set_max_response_data_size = ipmi_lan_set_max_rp_data_size,
|
|
+ .target_addr = IPMI_BMC_SLAVE_ADDR,
|
|
};
|
|
|
|
static struct ipmi_rq_entry *
|
|
@@ -214,6 +217,7 @@ ipmi_req_clear_entries(void)
|
|
}
|
|
}
|
|
ipmi_req_entries = NULL;
|
|
+ ipmi_req_entries_tail = NULL;
|
|
}
|
|
|
|
static int
|
|
@@ -248,7 +252,8 @@ static struct ipmi_rs *
|
|
ipmi_lan_recv_packet(struct ipmi_intf * intf)
|
|
{
|
|
static struct ipmi_rs rsp;
|
|
- fd_set read_set, err_set;
|
|
+ fd_set read_set;
|
|
+ fd_set err_set;
|
|
struct timeval tmout;
|
|
int ret;
|
|
|
|
@@ -258,7 +263,7 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf)
|
|
FD_ZERO(&err_set);
|
|
FD_SET(intf->fd, &err_set);
|
|
|
|
- tmout.tv_sec = intf->session->timeout;
|
|
+ tmout.tv_sec = intf->ssn_params.timeout;
|
|
tmout.tv_usec = 0;
|
|
|
|
ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
|
|
@@ -284,7 +289,7 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf)
|
|
FD_ZERO(&err_set);
|
|
FD_SET(intf->fd, &err_set);
|
|
|
|
- tmout.tv_sec = intf->session->timeout;
|
|
+ tmout.tv_sec = intf->ssn_params.timeout;
|
|
tmout.tv_usec = 0;
|
|
|
|
ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
|
|
@@ -813,7 +818,7 @@ ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req, int isRetry)
|
|
}
|
|
|
|
/* ipmi message header */
|
|
- msg[len++] = intf->target_addr;
|
|
+ msg[len++] = entry->bridging_level ? intf->target_addr : IPMI_BMC_SLAVE_ADDR;
|
|
msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
|
|
tmp = len - cs;
|
|
msg[len++] = ipmi_csum(msg+cs, tmp);
|
|
@@ -951,7 +956,7 @@ ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
break;
|
|
|
|
usleep(5000);
|
|
- if (++try >= intf->session->retry) {
|
|
+ if (++try >= intf->ssn_params.retry) {
|
|
lprintf(LOG_DEBUG, " No response from remote controller");
|
|
break;
|
|
}
|
|
@@ -1301,7 +1306,7 @@ ipmi_lan_send_sol_payload(struct ipmi_intf * intf,
|
|
}
|
|
|
|
usleep(5000);
|
|
- if (++try >= intf->session->retry) {
|
|
+ if (++try >= intf->ssn_params.retry) {
|
|
lprintf(LOG_DEBUG, " No response from remote controller");
|
|
break;
|
|
}
|
|
@@ -1548,10 +1553,12 @@ static int
|
|
ipmi_lan_keepalive(struct ipmi_intf * intf)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req = { msg: {
|
|
- netfn: IPMI_NETFN_APP,
|
|
- cmd: 1,
|
|
- }};
|
|
+ struct ipmi_rq req = {
|
|
+ .msg = {
|
|
+ .netfn = IPMI_NETFN_APP,
|
|
+ .cmd = 1,
|
|
+ }
|
|
+ };
|
|
|
|
if (!intf->opened)
|
|
return 0;
|
|
@@ -1574,10 +1581,11 @@ ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf)
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
struct ipmi_session * s = intf->session;
|
|
+ struct ipmi_session_params *p = &intf->ssn_params;
|
|
uint8_t msg_data[2];
|
|
|
|
msg_data[0] = IPMI_LAN_CHANNEL_E;
|
|
- msg_data[1] = s->privlvl;
|
|
+ msg_data[1] = p->privlvl;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_APP;
|
|
@@ -1628,44 +1636,44 @@ ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf)
|
|
|
|
s->authstatus = rsp->data[2];
|
|
|
|
- if (s->password &&
|
|
- (s->authtype_set == 0 ||
|
|
- s->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) &&
|
|
+ if (p->password &&
|
|
+ (p->authtype_set == 0 ||
|
|
+ p->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) &&
|
|
(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5))
|
|
{
|
|
s->authtype = IPMI_SESSION_AUTHTYPE_MD5;
|
|
}
|
|
- else if (s->password &&
|
|
- (s->authtype_set == 0 ||
|
|
- s->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) &&
|
|
+ else if (p->password &&
|
|
+ (p->authtype_set == 0 ||
|
|
+ p->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) &&
|
|
(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2))
|
|
{
|
|
s->authtype = IPMI_SESSION_AUTHTYPE_MD2;
|
|
}
|
|
- else if (s->password &&
|
|
- (s->authtype_set == 0 ||
|
|
- s->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) &&
|
|
+ else if (p->password &&
|
|
+ (p->authtype_set == 0 ||
|
|
+ p->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) &&
|
|
(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD))
|
|
{
|
|
s->authtype = IPMI_SESSION_AUTHTYPE_PASSWORD;
|
|
}
|
|
- else if (s->password &&
|
|
- (s->authtype_set == 0 ||
|
|
- s->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) &&
|
|
+ else if (p->password &&
|
|
+ (p->authtype_set == 0 ||
|
|
+ p->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) &&
|
|
(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM))
|
|
{
|
|
s->authtype = IPMI_SESSION_AUTHTYPE_OEM;
|
|
}
|
|
- else if ((s->authtype_set == 0 ||
|
|
- s->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) &&
|
|
+ else if ((p->authtype_set == 0 ||
|
|
+ p->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) &&
|
|
(rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE))
|
|
{
|
|
s->authtype = IPMI_SESSION_AUTHTYPE_NONE;
|
|
}
|
|
else {
|
|
- if (!(rsp->data[1] & 1<<s->authtype_set))
|
|
+ if (!(rsp->data[1] & 1<<p->authtype_set))
|
|
lprintf(LOG_ERR, "Authentication type %s not supported",
|
|
- val2str(s->authtype_set, ipmi_authtype_session_vals));
|
|
+ val2str(p->authtype_set, ipmi_authtype_session_vals));
|
|
else
|
|
lprintf(LOG_ERR, "No supported authtypes found");
|
|
|
|
@@ -1692,7 +1700,7 @@ ipmi_get_session_challenge_cmd(struct ipmi_intf * intf)
|
|
|
|
memset(msg_data, 0, 17);
|
|
msg_data[0] = s->authtype;
|
|
- memcpy(msg_data+1, s->username, 16);
|
|
+ memcpy(msg_data+1, intf->ssn_params.username, 16);
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_APP;
|
|
@@ -1749,12 +1757,12 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf)
|
|
req.msg.cmd = 0x3a;
|
|
|
|
msg_data[0] = s->authtype;
|
|
- msg_data[1] = s->privlvl;
|
|
+ msg_data[1] = intf->ssn_params.privlvl;
|
|
|
|
/* supermicro oem authentication hack */
|
|
if (ipmi_oem_active(intf, "supermicro")) {
|
|
uint8_t * special = ipmi_auth_special(s);
|
|
- memcpy(s->authcode, special, 16);
|
|
+ memcpy(intf->session->authcode, special, 16);
|
|
memset(msg_data + 2, 0, 16);
|
|
lprintf(LOG_DEBUG, " OEM Auth : %s",
|
|
buf2str(special, 16));
|
|
@@ -1831,8 +1839,6 @@ ipmi_activate_session_cmd(struct ipmi_intf * intf)
|
|
return -1;
|
|
}
|
|
|
|
- bridge_possible = 1;
|
|
-
|
|
lprintf(LOG_DEBUG, "\nSession Activated");
|
|
lprintf(LOG_DEBUG, " Auth Type : %s",
|
|
val2str(rsp->data[0], ipmi_authtype_session_vals));
|
|
@@ -1853,7 +1859,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
- uint8_t privlvl = intf->session->privlvl;
|
|
+ uint8_t privlvl = intf->ssn_params.privlvl;
|
|
uint8_t backup_bridge_possible = bridge_possible;
|
|
|
|
if (privlvl <= IPMI_SESSION_PRIV_USER)
|
|
@@ -1986,23 +1992,27 @@ ipmi_lan_activate_session(struct ipmi_intf * intf)
|
|
|
|
rc = ipmi_set_session_privlvl_cmd(intf);
|
|
if (rc < 0)
|
|
- goto fail;
|
|
+ goto close_fail;
|
|
|
|
return 0;
|
|
|
|
+ close_fail:
|
|
+ ipmi_close_session_cmd(intf);
|
|
fail:
|
|
lprintf(LOG_ERR, "Error: Unable to establish LAN session");
|
|
return -1;
|
|
}
|
|
|
|
-static void
|
|
+void
|
|
ipmi_lan_close(struct ipmi_intf * intf)
|
|
{
|
|
- if (intf->abort == 0)
|
|
+ if (!intf->abort && intf->session)
|
|
ipmi_close_session_cmd(intf);
|
|
|
|
- if (intf->fd >= 0)
|
|
+ if (intf->fd >= 0) {
|
|
close(intf->fd);
|
|
+ intf->fd = -1;
|
|
+ }
|
|
|
|
ipmi_req_clear_entries();
|
|
ipmi_intf_session_cleanup(intf);
|
|
@@ -2016,69 +2026,78 @@ ipmi_lan_open(struct ipmi_intf * intf)
|
|
{
|
|
int rc;
|
|
struct ipmi_session *s;
|
|
+ struct ipmi_session_params *p;
|
|
|
|
- if (intf == NULL || intf->session == NULL)
|
|
+ if (intf == NULL || intf->opened)
|
|
return -1;
|
|
- s = intf->session;
|
|
-
|
|
- 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 (s->hostname == NULL || strlen((const char *)s->hostname) == 0) {
|
|
+ s = intf->session;
|
|
+ p = &intf->ssn_params;
|
|
+
|
|
+ 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 (p->hostname == NULL || strlen((const char *)p->hostname) == 0) {
|
|
lprintf(LOG_ERR, "No hostname specified!");
|
|
return -1;
|
|
}
|
|
|
|
- intf->abort = 1;
|
|
-
|
|
- intf->session->sol_data.sequence_number = 1;
|
|
-
|
|
- if (ipmi_intf_socket_connect (intf) == -1) {
|
|
+ if (ipmi_intf_socket_connect(intf) == -1) {
|
|
lprintf(LOG_ERR, "Could not open socket!");
|
|
return -1;
|
|
}
|
|
|
|
- if (intf->fd < 0) {
|
|
- lperror(LOG_ERR, "Connect to %s failed",
|
|
- s->hostname);
|
|
- intf->close(intf);
|
|
- return -1;
|
|
+ s = (struct ipmi_session *)malloc(sizeof(struct ipmi_session));
|
|
+ if (!s) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ goto fail;
|
|
}
|
|
|
|
intf->opened = 1;
|
|
+ intf->abort = 1;
|
|
+
|
|
+ intf->session = s;
|
|
+
|
|
+ memset(s, 0, sizeof(struct ipmi_session));
|
|
+ s->sol_data.sequence_number = 1;
|
|
+ s->timeout = p->timeout;
|
|
+ memcpy(&s->authcode, &p->authcode_set, sizeof(s->authcode));
|
|
+ s->addrlen = sizeof(s->addr);
|
|
+ if (getsockname(intf->fd, (struct sockaddr *)&s->addr, &s->addrlen)) {
|
|
+ goto fail;
|
|
+ }
|
|
|
|
/* try to open session */
|
|
rc = ipmi_lan_activate_session(intf);
|
|
if (rc < 0) {
|
|
- intf->close(intf);
|
|
- intf->opened = 0;
|
|
- return -1;
|
|
+ goto fail;
|
|
}
|
|
|
|
- intf->manufacturer_id = ipmi_get_oem(intf);
|
|
-
|
|
/* automatically detect interface request and response sizes */
|
|
hpm2_detect_max_payload_size(intf);
|
|
|
|
+ /* set manufactirer OEM id */
|
|
+ intf->manufacturer_id = ipmi_get_oem(intf);
|
|
+
|
|
+ /* now allow bridging */
|
|
+ bridge_possible = 1;
|
|
return intf->fd;
|
|
+
|
|
+ fail:
|
|
+ lprintf(LOG_ERR, "Error: Unable to establish IPMI v1.5 / RMCP session");
|
|
+ intf->close(intf);
|
|
+ return -1;
|
|
}
|
|
|
|
static int
|
|
ipmi_lan_setup(struct ipmi_intf * intf)
|
|
{
|
|
- intf->session = malloc(sizeof(struct ipmi_session));
|
|
- if (intf->session == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
- memset(intf->session, 0, sizeof(struct ipmi_session));
|
|
-
|
|
/* setup default LAN maximum request and response sizes */
|
|
intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
|
|
intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
|
|
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
|
|
index 0bff5b2..490d3f5 100644
|
|
--- a/src/plugins/lanplus/lanplus.c
|
|
+++ b/src/plugins/lanplus/lanplus.c
|
|
@@ -29,12 +29,15 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
+#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/select.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
@@ -126,18 +129,18 @@ static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t siz
|
|
static uint8_t bridgePossible = 0;
|
|
|
|
struct ipmi_intf ipmi_lanplus_intf = {
|
|
- name: "lanplus",
|
|
- desc: "IPMI v2.0 RMCP+ LAN Interface",
|
|
- setup: ipmi_lanplus_setup,
|
|
- open: ipmi_lanplus_open,
|
|
- close: ipmi_lanplus_close,
|
|
- sendrecv: ipmi_lanplus_send_ipmi_cmd,
|
|
- recv_sol: ipmi_lanplus_recv_sol,
|
|
- send_sol: ipmi_lanplus_send_sol,
|
|
- keepalive: ipmi_lanplus_keepalive,
|
|
- set_max_request_data_size: ipmi_lanp_set_max_rq_data_size,
|
|
- set_max_response_data_size: ipmi_lanp_set_max_rp_data_size,
|
|
- target_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+ .name = "lanplus",
|
|
+ .desc = "IPMI v2.0 RMCP+ LAN Interface",
|
|
+ .setup = ipmi_lanplus_setup,
|
|
+ .open = ipmi_lanplus_open,
|
|
+ .close = ipmi_lanplus_close,
|
|
+ .sendrecv = ipmi_lanplus_send_ipmi_cmd,
|
|
+ .recv_sol = ipmi_lanplus_recv_sol,
|
|
+ .send_sol = ipmi_lanplus_send_sol,
|
|
+ .keepalive = ipmi_lanplus_keepalive,
|
|
+ .set_max_request_data_size = ipmi_lanp_set_max_rq_data_size,
|
|
+ .set_max_response_data_size = ipmi_lanp_set_max_rp_data_size,
|
|
+ .target_addr = IPMI_BMC_SLAVE_ADDR,
|
|
};
|
|
|
|
|
|
@@ -383,6 +386,9 @@ ipmi_req_clear_entries(void)
|
|
free(e);
|
|
e = p;
|
|
}
|
|
+
|
|
+ ipmi_req_entries = NULL;
|
|
+ ipmi_req_entries_tail = NULL;
|
|
}
|
|
|
|
|
|
@@ -595,7 +601,7 @@ ipmiv2_lan_ping(struct ipmi_intf * intf)
|
|
|
|
/**
|
|
*
|
|
- * ipmi_lan_poll_recv
|
|
+ * ipmi_lan_poll_single
|
|
*
|
|
* Receive whatever comes back. Ignore received packets that don't correspond
|
|
* to a request we've sent.
|
|
@@ -603,99 +609,88 @@ ipmiv2_lan_ping(struct ipmi_intf * intf)
|
|
* Returns: the ipmi_rs packet describing the/a reponse we expect.
|
|
*/
|
|
static struct ipmi_rs *
|
|
-ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
|
+ipmi_lan_poll_single(struct ipmi_intf * intf)
|
|
{
|
|
- struct rmcp_hdr rmcp_rsp;
|
|
+ struct rmcp_hdr * rmcp_rsp;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_session * session = intf->session;
|
|
int offset, rv;
|
|
uint16_t payload_size;
|
|
- uint8_t ourAddress = intf->my_addr;
|
|
-
|
|
- if (ourAddress == 0) {
|
|
- ourAddress = IPMI_BMC_SLAVE_ADDR;
|
|
- }
|
|
|
|
+ /* receive packet */
|
|
rsp = ipmi_lan_recv_packet(intf);
|
|
|
|
- /*
|
|
- * Not positive why we're looping. Do we sometimes get stuff we don't
|
|
- * expect?
|
|
- */
|
|
- while (rsp != NULL) {
|
|
-
|
|
- /* parse response headers */
|
|
- memcpy(&rmcp_rsp, rsp->data, 4);
|
|
-
|
|
- if (rmcp_rsp.class == RMCP_CLASS_ASF) {
|
|
- /* might be ping response packet */
|
|
- rv = ipmi_handle_pong(intf, rsp);
|
|
- return (rv <= 0) ? NULL : rsp;
|
|
- }
|
|
+ /* check if no packet has come */
|
|
+ if (rsp == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
|
|
- if (rmcp_rsp.class != RMCP_CLASS_IPMI) {
|
|
- lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
|
|
- rmcp_rsp.class);
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
- }
|
|
+ /* parse response headers */
|
|
+ rmcp_rsp = (struct rmcp_hdr *)rsp->data;
|
|
|
|
+ if (rmcp_rsp->class == RMCP_CLASS_ASF) {
|
|
+ /* might be ping response packet */
|
|
+ rv = ipmi_handle_pong(intf, rsp);
|
|
+ return (rv <= 0) ? NULL : rsp;
|
|
+ }
|
|
|
|
- /*
|
|
- * The authtype / payload type determines what we are receiving
|
|
- */
|
|
- offset = 4;
|
|
-
|
|
-
|
|
- /*--------------------------------------------------------------------
|
|
- *
|
|
- * The current packet could be one of several things:
|
|
- *
|
|
- * 1) An IPMI 1.5 packet (the response to our GET CHANNEL
|
|
- * AUTHENTICATION CAPABILITIES request)
|
|
- * 2) An RMCP+ message with an IPMI reponse payload
|
|
- * 3) AN RMCP+ open session response
|
|
- * 4) An RAKP-2 message (response to an RAKP 1 message)
|
|
- * 5) An RAKP-4 message (response to an RAKP 3 message)
|
|
- * 6) A Serial Over LAN packet
|
|
- * 7) An Invalid packet (one that doesn't match a request)
|
|
- * -------------------------------------------------------------------
|
|
- */
|
|
+ if (rmcp_rsp->class != RMCP_CLASS_IPMI) {
|
|
+ lprintf(LOG_DEBUG, "Invalid RMCP class: %x", rmcp_rsp->class);
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
+ }
|
|
|
|
- read_session_data(rsp, &offset, intf->session);
|
|
+ /*
|
|
+ * The authtype / payload type determines what we are receiving
|
|
+ */
|
|
+ offset = 4;
|
|
|
|
- if (lanplus_has_valid_auth_code(rsp, intf->session) == 0)
|
|
- {
|
|
- lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- assert(0);
|
|
- //continue;
|
|
- }
|
|
+ /*--------------------------------------------------------------------
|
|
+ *
|
|
+ * The current packet could be one of several things:
|
|
+ *
|
|
+ * 1) An IPMI 1.5 packet (the response to our GET CHANNEL
|
|
+ * AUTHENTICATION CAPABILITIES request)
|
|
+ * 2) An RMCP+ message with an IPMI reponse payload
|
|
+ * 3) AN RMCP+ open session response
|
|
+ * 4) An RAKP-2 message (response to an RAKP 1 message)
|
|
+ * 5) An RAKP-4 message (response to an RAKP 3 message)
|
|
+ * 6) A Serial Over LAN packet
|
|
+ * 7) An Invalid packet (one that doesn't match a request)
|
|
+ * -------------------------------------------------------------------
|
|
+ */
|
|
|
|
- if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
|
|
- (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
|
|
- (rsp->session.bEncrypted))
|
|
+ read_session_data(rsp, &offset, intf->session);
|
|
|
|
- {
|
|
- lanplus_decrypt_payload(session->v2_data.crypt_alg,
|
|
- session->v2_data.k2,
|
|
- rsp->data + offset,
|
|
- rsp->session.msglen,
|
|
- rsp->data + offset,
|
|
- &payload_size);
|
|
- }
|
|
- else
|
|
- payload_size = rsp->session.msglen;
|
|
+ if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) {
|
|
+ lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!");
|
|
+ return NULL;
|
|
+ }
|
|
|
|
+ if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
|
|
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
|
|
+ (rsp->session.bEncrypted)) {
|
|
+ lanplus_decrypt_payload(session->v2_data.crypt_alg,
|
|
+ session->v2_data.k2,
|
|
+ rsp->data + offset,
|
|
+ rsp->session.msglen,
|
|
+ rsp->data + offset,
|
|
+ &payload_size);
|
|
+ } else {
|
|
+ payload_size = rsp->session.msglen;
|
|
+ }
|
|
|
|
- /*
|
|
- * Handle IPMI responses (case #1 and #2) -- all IPMI reponses
|
|
- */
|
|
- if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI)
|
|
- {
|
|
- struct ipmi_rq_entry * entry;
|
|
- int payload_start = offset;
|
|
- int extra_data_length;
|
|
+ /*
|
|
+ * Handle IPMI responses (case #1 and #2) -- all IPMI reponses
|
|
+ */
|
|
+ if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) {
|
|
+ struct ipmi_rq_entry * entry;
|
|
+ int payload_start = offset;
|
|
+ int extra_data_length;
|
|
+ int loop = 1;
|
|
+
|
|
+ while (loop--) {
|
|
+ /* fill-in response data */
|
|
read_ipmi_response(rsp, &offset);
|
|
|
|
lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
|
|
@@ -731,159 +726,154 @@ ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
|
entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
|
|
rsp->payload.ipmi_response.cmd);
|
|
|
|
- if (entry != NULL) {
|
|
- lprintf(LOG_DEBUG+2, "IPMI Request Match found");
|
|
- if ( intf->target_addr != intf->my_addr &&
|
|
- bridgePossible &&
|
|
- rsp->data_len &&
|
|
- rsp->payload.ipmi_response.cmd == 0x34 &&
|
|
- (rsp->payload.ipmi_response.netfn == 0x06 ||
|
|
- rsp->payload.ipmi_response.netfn == 0x07) &&
|
|
- rsp->payload.ipmi_response.rs_lun == 0 )
|
|
- {
|
|
- /* Check completion code */
|
|
- if (rsp->data[offset-1] == 0)
|
|
- {
|
|
- lprintf(LOG_DEBUG, "Bridged command answer,"
|
|
- " waiting for next answer... ");
|
|
- ipmi_req_remove_entry(
|
|
- rsp->payload.ipmi_response.rq_seq,
|
|
- rsp->payload.ipmi_response.cmd);
|
|
- return ipmi_lan_poll_recv(intf);
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_DEBUG, "WARNING: Bridged "
|
|
- "cmd ccode = 0x%02x",
|
|
- rsp->data[offset-1]);
|
|
+ if (entry == NULL) {
|
|
+ lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
+ };
|
|
+
|
|
+ uint8_t target_cmd = entry->req.msg.target_cmd;
|
|
+
|
|
+ lprintf(LOG_DEBUG+2, "IPMI Request Match found");
|
|
+
|
|
+ if (entry->bridging_level) {
|
|
+ /* Check completion code */
|
|
+ if (rsp->ccode) {
|
|
+ lprintf(LOG_DEBUG, "WARNING: Bridged "
|
|
+ "cmd ccode = 0x%02x", rsp->ccode);
|
|
+ } else {
|
|
+ /* decrement bridging level */
|
|
+ entry->bridging_level--;
|
|
+ if (!entry->bridging_level) {
|
|
+ entry->req.msg.cmd = entry->req.msg.target_cmd;
|
|
}
|
|
|
|
- if (rsp->data_len &&
|
|
- rsp->payload.ipmi_response.cmd == 0x34) {
|
|
- memcpy(rsp->data, &rsp->data[offset],
|
|
- (rsp->data_len-offset));
|
|
- if (verbose > 2)
|
|
- printbuf( &rsp->data[offset],
|
|
- (rsp->data_len-offset),
|
|
- "bridge command response");
|
|
+ /* check if bridged response is embedded */
|
|
+ if (payload_size > 8) {
|
|
+ printbuf(&rsp->data[offset], (rsp->data_len-offset-1),
|
|
+ "bridge command response");
|
|
+ /*
|
|
+ * decrement payload size
|
|
+ * (cks2 for outer Send Message)
|
|
+ */
|
|
+ payload_size--;
|
|
+
|
|
+ /*
|
|
+ * need to make a loop for embedded bridged response
|
|
+ */
|
|
+ loop++;
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "Bridged command answer,"
|
|
+ " waiting for next answer... ");
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
}
|
|
}
|
|
-
|
|
- ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
|
|
- rsp->payload.ipmi_response.cmd);
|
|
- } else {
|
|
- lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
}
|
|
|
|
+ /* Remove request entry */
|
|
+ ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
|
|
+ rsp->payload.ipmi_response.cmd);
|
|
+
|
|
/*
|
|
* Good packet. Shift response data to start of array.
|
|
* rsp->data becomes the variable length IPMI response data
|
|
* rsp->data_len becomes the length of that data
|
|
*/
|
|
extra_data_length = payload_size - (offset - payload_start) - 1;
|
|
- if (rsp != NULL && extra_data_length)
|
|
- {
|
|
+ if (extra_data_length) {
|
|
rsp->data_len = extra_data_length;
|
|
memmove(rsp->data, rsp->data + offset, extra_data_length);
|
|
- }
|
|
- else
|
|
+ } else {
|
|
rsp->data_len = 0;
|
|
-
|
|
- break;
|
|
+ }
|
|
}
|
|
-
|
|
-
|
|
- /*
|
|
- * Open Response
|
|
- */
|
|
- else if (rsp->session.payloadtype ==
|
|
- IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
|
|
- {
|
|
- if (session->v2_data.session_state !=
|
|
- LANPLUS_STATE_OPEN_SESSION_SENT)
|
|
- {
|
|
- lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
|
|
+ /*
|
|
+ * Open Response
|
|
+ */
|
|
+ } else if (rsp->session.payloadtype ==
|
|
+ IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) {
|
|
+ if (session->v2_data.session_state !=
|
|
+ LANPLUS_STATE_OPEN_SESSION_SENT) {
|
|
+ lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
|
|
"Response");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
- }
|
|
-
|
|
- read_open_session_response(rsp, offset);
|
|
- break;
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
}
|
|
-
|
|
-
|
|
- /*
|
|
- * RAKP 2
|
|
- */
|
|
- else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2)
|
|
- {
|
|
- if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT)
|
|
- {
|
|
- lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
- }
|
|
-
|
|
- read_rakp2_message(rsp, offset, session->v2_data.auth_alg);
|
|
- break;
|
|
+ read_open_session_response(rsp, offset);
|
|
+ /*
|
|
+ * RAKP 2
|
|
+ */
|
|
+ } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) {
|
|
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) {
|
|
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message");
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
}
|
|
-
|
|
-
|
|
- /*
|
|
- * RAKP 4
|
|
- */
|
|
- else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4)
|
|
- {
|
|
- if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT)
|
|
- {
|
|
- lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
- }
|
|
-
|
|
- read_rakp4_message(rsp, offset, session->v2_data.auth_alg);
|
|
- break;
|
|
+ read_rakp2_message(rsp, offset, session->v2_data.auth_alg);
|
|
+ /*
|
|
+ * RAKP 4
|
|
+ */
|
|
+ } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) {
|
|
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) {
|
|
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message");
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
}
|
|
+ read_rakp4_message(rsp, offset, session->v2_data.auth_alg);
|
|
+ /*
|
|
+ * SOL
|
|
+ */
|
|
+ } else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) {
|
|
+ int payload_start = offset;
|
|
+ int extra_data_length;
|
|
+
|
|
+ if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) {
|
|
+ lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet");
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
+ }
|
|
+ read_sol_packet(rsp, &offset);
|
|
+ extra_data_length = payload_size - (offset - payload_start);
|
|
+ if (rsp && extra_data_length) {
|
|
+ rsp->data_len = extra_data_length;
|
|
+ memmove(rsp->data, rsp->data + offset, extra_data_length);
|
|
+ } else {
|
|
+ rsp->data_len = 0;
|
|
+ }
|
|
+ /*
|
|
+ * Unknown Payload type
|
|
+ */
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
|
|
+ rsp->session.payloadtype);
|
|
+ /* read one more packet */
|
|
+ return (struct ipmi_rs *)1;
|
|
+ }
|
|
|
|
+ return rsp;
|
|
+}
|
|
|
|
- /*
|
|
- * SOL
|
|
- */
|
|
- else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)
|
|
- {
|
|
- int payload_start = offset;
|
|
- int extra_data_length;
|
|
-
|
|
- if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
|
|
- {
|
|
- lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet");
|
|
- rsp = ipmi_lan_recv_packet(intf);
|
|
- continue;
|
|
- }
|
|
|
|
- read_sol_packet(rsp, &offset);
|
|
- extra_data_length = payload_size - (offset - payload_start);
|
|
- if (rsp && extra_data_length)
|
|
- {
|
|
- rsp->data_len = extra_data_length;
|
|
- memmove(rsp->data, rsp->data + offset, extra_data_length);
|
|
- }
|
|
- else
|
|
- rsp->data_len = 0;
|
|
|
|
- break;
|
|
- }
|
|
+/**
|
|
+ *
|
|
+ * ipmi_lan_poll_recv
|
|
+ *
|
|
+ * Receive whatever comes back. Ignore received packets that don't correspond
|
|
+ * to a request we've sent.
|
|
+ *
|
|
+ * Returns: the ipmi_rs packet describing the/a reponse we expect.
|
|
+ */
|
|
+static struct ipmi_rs *
|
|
+ipmi_lan_poll_recv(struct ipmi_intf * intf)
|
|
+{
|
|
+ struct ipmi_rs * rsp;
|
|
|
|
- else
|
|
- {
|
|
- lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
|
|
- rsp->session.payloadtype);
|
|
- assert(0);
|
|
- }
|
|
- }
|
|
+ do {
|
|
+ /* poll single packet */
|
|
+ rsp = ipmi_lan_poll_single(intf);
|
|
+ } while (rsp == (struct ipmi_rs *) 1);
|
|
|
|
return rsp;
|
|
}
|
|
@@ -1406,7 +1396,7 @@ void getIpmiPayloadWireRep(
|
|
tmp = len - cs;
|
|
msg[len++] = ipmi_csum(msg+cs, tmp);
|
|
cs3 = len;
|
|
- msg[len++] = intf->my_addr;
|
|
+ msg[len++] = IPMI_REMOTE_SWID;
|
|
msg[len++] = curr_seq << 2;
|
|
msg[len++] = 0x34; /* Send Message rqst */
|
|
#if 0 /* From lan.c example */
|
|
@@ -1429,7 +1419,10 @@ void getIpmiPayloadWireRep(
|
|
bridgePossible);
|
|
|
|
/* rsAddr */
|
|
- msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */
|
|
+ if (bridgedRequest)
|
|
+ msg[len++] = intf->target_addr;
|
|
+ else
|
|
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
|
|
|
|
/* net Fn */
|
|
msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
|
|
@@ -1440,7 +1433,7 @@ void getIpmiPayloadWireRep(
|
|
cs = len;
|
|
|
|
/* rqAddr */
|
|
- if (!bridgedRequest)
|
|
+ if (bridgedRequest < 2)
|
|
msg[len++] = IPMI_REMOTE_SWID;
|
|
else /* Bridged message */
|
|
msg[len++] = intf->my_addr;
|
|
@@ -1690,7 +1683,7 @@ ipmi_lanplus_build_v2x_msg(
|
|
curr_seq);
|
|
break;
|
|
|
|
- case IPMI_PAYLOAD_TYPE_SOL:
|
|
+ case IPMI_PAYLOAD_TYPE_SOL:
|
|
getSolPayloadWireRep(intf,
|
|
msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
|
|
payload);
|
|
@@ -1890,26 +1883,26 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
|
|
|
|
|
|
/* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
|
|
- if ((intf->target_addr == intf->my_addr) || (!bridgePossible))
|
|
- {
|
|
- entry = ipmi_req_add_entry(intf, req, curr_seq);
|
|
- }
|
|
- else /* it's a bridge command */
|
|
- {
|
|
- unsigned char backup_cmd;
|
|
-
|
|
- /* Add entry for cmd */
|
|
- entry = ipmi_req_add_entry(intf, req, curr_seq);
|
|
-
|
|
- if(entry)
|
|
- {
|
|
- /* Add entry for bridge cmd */
|
|
- backup_cmd = req->msg.cmd;
|
|
- req->msg.cmd = 0x34;
|
|
- entry = ipmi_req_add_entry(intf, req, curr_seq);
|
|
- req->msg.cmd = backup_cmd;
|
|
- }
|
|
- }
|
|
+ if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) {
|
|
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
|
|
+ /* it's a bridge command */
|
|
+ } else {
|
|
+ unsigned char backup_cmd;
|
|
+
|
|
+ /* Add entry for cmd */
|
|
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
|
|
+
|
|
+ if (entry) {
|
|
+ entry->req.msg.target_cmd = entry->req.msg.cmd;
|
|
+ entry->req.msg.cmd = 0x34;
|
|
+
|
|
+ if (intf->transit_addr &&
|
|
+ intf->transit_addr != intf->my_addr)
|
|
+ entry->bridging_level = 2;
|
|
+ else
|
|
+ entry->bridging_level = 1;
|
|
+ }
|
|
+ }
|
|
|
|
if (entry == NULL)
|
|
return NULL;
|
|
@@ -2125,7 +2118,7 @@ ipmi_lanplus_send_payload(
|
|
* so it will only be valid after the open completes.
|
|
*/
|
|
saved_timeout = session->timeout;
|
|
- while (try < session->retry) {
|
|
+ while (try < intf->ssn_params.retry) {
|
|
//ltime = time(NULL);
|
|
|
|
if (xmit) {
|
|
@@ -2263,16 +2256,16 @@ ipmi_lanplus_send_payload(
|
|
case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
|
|
session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT;
|
|
/* not retryable for timeouts, force no retry */
|
|
- try = session->retry;
|
|
+ try = intf->ssn_params.retry;
|
|
break;
|
|
case IPMI_PAYLOAD_TYPE_RAKP_1:
|
|
session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT;
|
|
/* not retryable for timeouts, force no retry */
|
|
- try = session->retry;
|
|
+ try = intf->ssn_params.retry;
|
|
break;
|
|
case IPMI_PAYLOAD_TYPE_RAKP_3:
|
|
/* not retryable for timeouts, force no retry */
|
|
- try = session->retry;
|
|
+ try = intf->ssn_params.retry;
|
|
session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT;
|
|
break;
|
|
}
|
|
@@ -2574,7 +2567,7 @@ ack_sol_packet(
|
|
{
|
|
struct ipmi_v2_payload ack;
|
|
|
|
- bzero(&ack, sizeof(struct ipmi_v2_payload));
|
|
+ memset(&ack, 0, sizeof(struct ipmi_v2_payload));
|
|
|
|
ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
|
|
|
|
@@ -2677,7 +2670,7 @@ ipmi_get_auth_capabilities_cmd(
|
|
bridgePossible = 0;
|
|
|
|
msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well
|
|
- msg_data[1] = intf->session->privlvl;
|
|
+ msg_data[1] = intf->ssn_params.privlvl;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_APP; // 0x06
|
|
@@ -2728,7 +2721,8 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
|
|
uint32_t bmc_session_lsbf;
|
|
uint8_t backupBridgePossible;
|
|
|
|
- if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
|
|
+ if (intf->session == NULL
|
|
+ || intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
|
|
return -1;
|
|
|
|
backupBridgePossible = bridgePossible;
|
|
@@ -2809,8 +2803,8 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf)
|
|
memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE);
|
|
|
|
msg[0] = 0; /* Message tag */
|
|
- if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN)
|
|
- msg[1] = session->privlvl;
|
|
+ if (ipmi_oem_active(intf, "intelplus") || intf->ssn_params.privlvl != IPMI_SESSION_PRIV_ADMIN)
|
|
+ msg[1] = intf->ssn_params.privlvl;
|
|
else
|
|
msg[1] = 0; /* Give us highest privlg level based on supported algorithms */
|
|
msg[2] = 0; /* reserved */
|
|
@@ -2824,13 +2818,13 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf)
|
|
msg[7] = (session->v2_data.console_id >> 24) & 0xff;
|
|
|
|
|
|
- if (lanplus_get_requested_ciphers(session->cipher_suite_id,
|
|
+ if (lanplus_get_requested_ciphers(intf->ssn_params.cipher_suite_id,
|
|
&(session->v2_data.requested_auth_alg),
|
|
&(session->v2_data.requested_integrity_alg),
|
|
&(session->v2_data.requested_crypt_alg)))
|
|
{
|
|
lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n",
|
|
- session->cipher_suite_id);
|
|
+ intf->ssn_params.cipher_suite_id);
|
|
free(msg);
|
|
msg = NULL;
|
|
return 1;
|
|
@@ -3030,14 +3024,14 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
|
|
/*
|
|
* Requested maximum privilege level.
|
|
*/
|
|
- msg[24] = session->privlvl | session->v2_data.lookupbit;
|
|
+ msg[24] = intf->ssn_params.privlvl | intf->ssn_params.lookupbit;
|
|
session->v2_data.requested_role = msg[24];
|
|
msg[25] = 0; /* reserved */
|
|
msg[26] = 0; /* reserved */
|
|
|
|
|
|
/* Username specification */
|
|
- msg[27] = strlen((const char *)session->username);
|
|
+ msg[27] = strlen((const char *)intf->ssn_params.username);
|
|
if (msg[27] > IPMI_MAX_USER_NAME_LENGTH)
|
|
{
|
|
lprintf(LOG_ERR, "ERROR: user name too long. "
|
|
@@ -3047,11 +3041,20 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
|
|
msg = NULL;
|
|
return 1;
|
|
}
|
|
- memcpy(msg + 28, session->username, msg[27]);
|
|
+ memcpy(msg + 28, intf->ssn_params.username, msg[27]);
|
|
|
|
- v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1;
|
|
- v2_payload.payload_length =
|
|
- IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]);
|
|
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1;
|
|
+ if (ipmi_oem_active(intf, "i82571spt")) {
|
|
+ /*
|
|
+ * The IPMI v2.0 spec hints on that all user name bytes
|
|
+ * must be occupied (29:44). The Intel 82571 GbE refuses
|
|
+ * to establish a session if this field is shorter.
|
|
+ */
|
|
+ v2_payload.payload_length = IPMI_RAKP1_MESSAGE_SIZE;
|
|
+ } else {
|
|
+ v2_payload.payload_length =
|
|
+ IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]);
|
|
+ }
|
|
v2_payload.payload.rakp_1_message.message = msg;
|
|
|
|
rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
|
|
@@ -3284,15 +3287,16 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf)
|
|
void
|
|
ipmi_lanplus_close(struct ipmi_intf * intf)
|
|
{
|
|
- if (!intf->abort)
|
|
+ if (!intf->abort && intf->session)
|
|
ipmi_close_session_cmd(intf);
|
|
|
|
- if (intf->fd >= 0)
|
|
+ if (intf->fd >= 0) {
|
|
close(intf->fd);
|
|
+ intf->fd = -1;
|
|
+ }
|
|
|
|
ipmi_req_clear_entries();
|
|
ipmi_intf_session_cleanup(intf);
|
|
- intf->session = NULL;
|
|
intf->opened = 0;
|
|
intf->manufacturer_id = IPMI_OEM_UNKNOWN;
|
|
intf = NULL;
|
|
@@ -3306,7 +3310,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
uint8_t backupBridgePossible;
|
|
- uint8_t privlvl = intf->session->privlvl;
|
|
+ uint8_t privlvl = intf->ssn_params.privlvl;
|
|
|
|
if (privlvl <= IPMI_SESSION_PRIV_USER)
|
|
return 0; /* no need to set higher */
|
|
@@ -3356,55 +3360,54 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
int rc;
|
|
int retry;
|
|
struct get_channel_auth_cap_rsp auth_cap;
|
|
+ struct ipmi_session_params *params;
|
|
struct ipmi_session *session;
|
|
|
|
- if (!intf || !intf->session)
|
|
+ if (!intf)
|
|
return -1;
|
|
- session = intf->session;
|
|
-
|
|
- if (!session->port)
|
|
- session->port = IPMI_LANPLUS_PORT;
|
|
- if (!session->privlvl)
|
|
- session->privlvl = IPMI_SESSION_PRIV_ADMIN;
|
|
- if (!session->timeout)
|
|
- session->timeout = IPMI_LAN_TIMEOUT;
|
|
- if (!session->retry)
|
|
- session->retry = IPMI_LAN_RETRY;
|
|
-
|
|
- if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
|
|
+
|
|
+ if (intf->opened)
|
|
+ return intf->fd;
|
|
+
|
|
+ params = &intf->ssn_params;
|
|
+
|
|
+ if (!params->port)
|
|
+ params->port = IPMI_LANPLUS_PORT;
|
|
+ if (!params->privlvl)
|
|
+ params->privlvl = IPMI_SESSION_PRIV_ADMIN;
|
|
+ if (!params->timeout)
|
|
+ params->timeout = IPMI_LAN_TIMEOUT;
|
|
+ if (!params->retry)
|
|
+ params->retry = IPMI_LAN_RETRY;
|
|
+
|
|
+ if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
|
|
lprintf(LOG_ERR, "No hostname specified!");
|
|
return -1;
|
|
}
|
|
|
|
- intf->abort = 1;
|
|
+ if (ipmi_intf_socket_connect(intf) == -1) {
|
|
+ lprintf(LOG_ERR, "Could not open socket!");
|
|
+ goto fail;
|
|
+ }
|
|
|
|
+ session = (struct ipmi_session *)malloc(sizeof (struct ipmi_session));
|
|
+ if (!session) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ intf->session = session;
|
|
|
|
/* Setup our lanplus session state */
|
|
+ memset(session, 0, sizeof(struct ipmi_session));
|
|
+ session->timeout = params->timeout;
|
|
+ memcpy(&session->authcode, ¶ms->authcode_set, sizeof(session->authcode));
|
|
session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE;
|
|
session->v2_data.crypt_alg = IPMI_CRYPT_NONE;
|
|
- session->v2_data.console_id = 0x00;
|
|
- session->v2_data.bmc_id = 0x00;
|
|
session->sol_data.sequence_number = 1;
|
|
- //session->sol_data.last_received_sequence_number = 0;
|
|
- //session->sol_data.last_received_byte_count = 0;
|
|
- memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
|
|
-
|
|
- /* Kg is set in ipmi_intf */
|
|
- //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
|
|
-
|
|
- if (ipmi_intf_socket_connect (intf) == -1) {
|
|
- lprintf(LOG_ERR, "Could not open socket!");
|
|
- return -1;
|
|
- }
|
|
-
|
|
- if (intf->fd < 0) {
|
|
- lperror(LOG_ERR, "Connect to %s failed",
|
|
- session->hostname);
|
|
- intf->close(intf);
|
|
- return -1;
|
|
- }
|
|
|
|
intf->opened = 1;
|
|
+ intf->abort = 1;
|
|
|
|
/*
|
|
*
|
|
@@ -3417,8 +3420,7 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
goto fail;
|
|
}
|
|
|
|
- if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available)
|
|
- {
|
|
+ if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) {
|
|
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
|
|
goto fail;
|
|
}
|
|
@@ -3434,7 +3436,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
* Open session
|
|
*/
|
|
if ((rc = ipmi_lanplus_open_session(intf)) == 1) {
|
|
- intf->close(intf);
|
|
goto fail;
|
|
}
|
|
if (rc == 2) {
|
|
@@ -3445,7 +3446,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
* RAKP 1
|
|
*/
|
|
if ((rc = ipmi_lanplus_rakp1(intf)) == 1) {
|
|
- intf->close(intf);
|
|
goto fail;
|
|
}
|
|
if (rc == 2) {
|
|
@@ -3456,7 +3456,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
* RAKP 3
|
|
*/
|
|
if ((rc = ipmi_lanplus_rakp3(intf)) == 1) {
|
|
- intf->close(intf);
|
|
goto fail;
|
|
}
|
|
if (rc == 0) break;
|
|
@@ -3465,24 +3464,25 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
|
|
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
|
|
|
|
+ intf->abort = 0;
|
|
+
|
|
if (!ipmi_oem_active(intf, "i82571spt")) {
|
|
rc = ipmi_set_session_privlvl_cmd(intf);
|
|
if (rc < 0) {
|
|
- intf->close(intf);
|
|
goto fail;
|
|
}
|
|
}
|
|
intf->manufacturer_id = ipmi_get_oem(intf);
|
|
- bridgePossible = 1;
|
|
|
|
/* automatically detect interface request and response sizes */
|
|
hpm2_detect_max_payload_size(intf);
|
|
|
|
+ bridgePossible = 1;
|
|
return intf->fd;
|
|
|
|
fail:
|
|
lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session");
|
|
- intf->opened = 0;
|
|
+ intf->close(intf);
|
|
return -1;
|
|
}
|
|
|
|
@@ -3582,10 +3582,12 @@ static int
|
|
ipmi_lanplus_keepalive(struct ipmi_intf * intf)
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req = { msg: {
|
|
- netfn: IPMI_NETFN_APP,
|
|
- cmd: 1,
|
|
- }};
|
|
+ struct ipmi_rq req = {
|
|
+ .msg = {
|
|
+ .netfn = IPMI_NETFN_APP,
|
|
+ .cmd = 1,
|
|
+ }
|
|
+ };
|
|
|
|
if (!intf->opened)
|
|
return 0;
|
|
@@ -3623,13 +3625,6 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf)
|
|
if (lanplus_seed_prng(16))
|
|
return -1;
|
|
|
|
- intf->session = malloc(sizeof(struct ipmi_session));
|
|
- if (intf->session == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
- memset(intf->session, 0, sizeof(struct ipmi_session));
|
|
-
|
|
/* setup default LAN maximum request and response sizes */
|
|
intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
|
|
intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
|
|
@@ -3639,7 +3634,7 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf)
|
|
|
|
static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
|
|
{
|
|
- if (intf->session->cipher_suite_id == 3) {
|
|
+ if (intf->ssn_params.cipher_suite_id == 3) {
|
|
/*
|
|
* encrypted payload can only be multiple of 16 bytes
|
|
*/
|
|
@@ -3657,7 +3652,7 @@ static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t siz
|
|
|
|
static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
|
|
{
|
|
- if (intf->session->cipher_suite_id == 3) {
|
|
+ if (intf->ssn_params.cipher_suite_id == 3) {
|
|
/*
|
|
* encrypted payload can only be multiple of 16 bytes
|
|
*/
|
|
diff --git a/src/plugins/lanplus/lanplus_crypt.c b/src/plugins/lanplus/lanplus_crypt.c
|
|
index 54fd5cb..1cdd050 100644
|
|
--- a/src/plugins/lanplus/lanplus_crypt.c
|
|
+++ b/src/plugins/lanplus/lanplus_crypt.c
|
|
@@ -95,7 +95,7 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
|
16 + /* GUIDc */
|
|
1 + /* ROLEm */
|
|
1 + /* ULENGTHm */
|
|
- strlen((const char *)session->username); /* optional */
|
|
+ strlen((const char *)intf->ssn_params.username); /* optional */
|
|
|
|
buffer = malloc(bufferLength);
|
|
if (buffer == NULL) {
|
|
@@ -163,11 +163,11 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
|
}
|
|
|
|
/* ULENGTHm */
|
|
- buffer[57] = strlen((const char *)session->username);
|
|
+ buffer[57] = strlen((const char *)intf->ssn_params.username);
|
|
|
|
/* UserName [optional] */
|
|
for (i = 0; i < buffer[57]; ++i)
|
|
- buffer[58 + i] = session->username[i];
|
|
+ buffer[58 + i] = intf->ssn_params.username[i];
|
|
|
|
if (verbose > 2)
|
|
{
|
|
@@ -375,7 +375,7 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
|
4 + /* SIDm */
|
|
1 + /* ROLEm */
|
|
1 + /* ULENGTHm */
|
|
- strlen((const char *)session->username);
|
|
+ strlen((const char *)intf->ssn_params.username);
|
|
|
|
input_buffer = malloc(input_buffer_length);
|
|
if (input_buffer == NULL) {
|
|
@@ -406,16 +406,16 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
|
|
|
/* ROLEm */
|
|
if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
|
|
- input_buffer[20] = session->privlvl;
|
|
+ input_buffer[20] = intf->ssn_params.privlvl;
|
|
else
|
|
input_buffer[20] = session->v2_data.requested_role;
|
|
|
|
/* ULENGTHm */
|
|
- input_buffer[21] = strlen((const char *)session->username);
|
|
+ input_buffer[21] = strlen((const char *)intf->ssn_params.username);
|
|
|
|
/* USERNAME */
|
|
for (i = 0; i < input_buffer[21]; ++i)
|
|
- input_buffer[22 + i] = session->username[i];
|
|
+ input_buffer[22 + i] = intf->ssn_params.username[i];
|
|
|
|
if (verbose > 2)
|
|
{
|
|
@@ -491,7 +491,7 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
|
16 + /* Rc */
|
|
1 + /* ROLEm */
|
|
1 + /* ULENGTHm */
|
|
- strlen((const char *)session->username);
|
|
+ strlen((const char *)intf->ssn_params.username);
|
|
|
|
input_buffer = malloc(input_buffer_length);
|
|
if (input_buffer == NULL) {
|
|
@@ -536,13 +536,13 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
|
}
|
|
|
|
/* ULENGTHm */
|
|
- input_buffer[33] = strlen((const char *)session->username);
|
|
+ input_buffer[33] = strlen((const char *)intf->ssn_params.username);
|
|
|
|
/* USERNAME */
|
|
for (i = 0; i < input_buffer[33]; ++i)
|
|
- input_buffer[34 + i] = session->username[i];
|
|
+ input_buffer[34 + i] = intf->ssn_params.username[i];
|
|
|
|
- if (session->v2_data.kg[0])
|
|
+ if (intf->ssn_params.kg[0])
|
|
{
|
|
/* We will be hashing with Kg */
|
|
/*
|
|
@@ -550,7 +550,7 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
|
* using Kg. It specifies that Kg should not be truncated.
|
|
* Kg is set in ipmi_intf.
|
|
*/
|
|
- input_key = session->v2_data.kg;
|
|
+ input_key = intf->ssn_params.kg;
|
|
}
|
|
else
|
|
{
|
|
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c
|
|
index f1ea0dd..fc685de 100644
|
|
--- a/src/plugins/open/open.c
|
|
+++ b/src/plugins/open/open.c
|
|
@@ -29,6 +29,7 @@
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
+#define _POSIX_SOURCE
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
@@ -38,6 +39,7 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/select.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <ipmitool/ipmi.h>
|
|
@@ -81,6 +83,9 @@
|
|
*/
|
|
#define IPMI_OPENIPMI_MAX_RS_DATA_SIZE 35
|
|
|
|
+/* Timeout for reading data from BMC in seconds */
|
|
+#define IPMI_OPENIPMI_READ_TIMEOUT 15
|
|
+
|
|
extern int verbose;
|
|
|
|
static int
|
|
@@ -164,19 +169,21 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
struct ipmi_recv recv;
|
|
struct ipmi_addr addr;
|
|
struct ipmi_system_interface_addr bmc_addr = {
|
|
- addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
|
|
- channel: IPMI_BMC_CHANNEL,
|
|
+ .addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
|
|
+ .channel = IPMI_BMC_CHANNEL,
|
|
};
|
|
struct ipmi_ipmb_addr ipmb_addr = {
|
|
- addr_type: IPMI_IPMB_ADDR_TYPE,
|
|
+ .addr_type = IPMI_IPMB_ADDR_TYPE,
|
|
};
|
|
struct ipmi_req _req;
|
|
static struct ipmi_rs rsp;
|
|
+ struct timeval read_timeout;
|
|
static int curr_seq = 0;
|
|
fd_set rset;
|
|
|
|
uint8_t * data = NULL;
|
|
int data_len = 0;
|
|
+ int retval = 0;
|
|
|
|
|
|
if (intf == NULL || req == NULL)
|
|
@@ -325,14 +332,23 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
|
|
FD_ZERO(&rset);
|
|
FD_SET(intf->fd, &rset);
|
|
-
|
|
- if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
|
|
+ read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT;
|
|
+ read_timeout.tv_usec = 0;
|
|
+ retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout);
|
|
+ if (retval < 0) {
|
|
lperror(LOG_ERR, "I/O Error");
|
|
if (data != NULL) {
|
|
free(data);
|
|
data = NULL;
|
|
}
|
|
return NULL;
|
|
+ } else if (retval == 0) {
|
|
+ lprintf(LOG_ERR, "No data available");
|
|
+ if (data != NULL) {
|
|
+ free(data);
|
|
+ data = NULL;
|
|
+ }
|
|
+ return NULL;
|
|
}
|
|
if (FD_ISSET(intf->fd, &rset) == 0) {
|
|
lprintf(LOG_ERR, "No data available");
|
|
@@ -375,8 +391,6 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
}
|
|
|
|
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
|
- uint8_t index = 0;
|
|
-
|
|
/* ipmb_addr.transit_slave_addr = intf->transit_addr; */
|
|
lprintf(LOG_DEBUG, "Decapsulating data received from transit "
|
|
"IPMB target @ 0x%x", intf->transit_addr);
|
|
@@ -432,13 +446,13 @@ int ipmi_openipmi_setup(struct ipmi_intf * intf)
|
|
}
|
|
|
|
struct ipmi_intf ipmi_open_intf = {
|
|
- name: "open",
|
|
- desc: "Linux OpenIPMI Interface",
|
|
- setup: ipmi_openipmi_setup,
|
|
- open: ipmi_openipmi_open,
|
|
- close: ipmi_openipmi_close,
|
|
- sendrecv: ipmi_openipmi_send_cmd,
|
|
- set_my_addr: ipmi_openipmi_set_my_addr,
|
|
- my_addr: IPMI_BMC_SLAVE_ADDR,
|
|
- target_addr: 0, /* init so -m local_addr does not cause bridging */
|
|
+ .name = "open",
|
|
+ .desc = "Linux OpenIPMI Interface",
|
|
+ .setup = ipmi_openipmi_setup,
|
|
+ .open = ipmi_openipmi_open,
|
|
+ .close = ipmi_openipmi_close,
|
|
+ .sendrecv = ipmi_openipmi_send_cmd,
|
|
+ .set_my_addr = ipmi_openipmi_set_my_addr,
|
|
+ .my_addr = IPMI_BMC_SLAVE_ADDR,
|
|
+ .target_addr = 0, /* init so -m local_addr does not cause bridging */
|
|
};
|
|
diff --git a/src/plugins/serial/serial_basic.c b/src/plugins/serial/serial_basic.c
|
|
index 871593f..fe2ebff 100644
|
|
--- a/src/plugins/serial/serial_basic.c
|
|
+++ b/src/plugins/serial/serial_basic.c
|
|
@@ -29,9 +29,11 @@
|
|
* 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.
|
|
*/
|
|
+#define _GNU_SOURCE 1
|
|
|
|
/* Serial Interface, Basic Mode plugin. */
|
|
|
|
+#include <alloca.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
@@ -183,16 +185,10 @@ static int is_system;
|
|
static int
|
|
serial_bm_setup(struct ipmi_intf * intf)
|
|
{
|
|
- intf->session = malloc(sizeof(struct ipmi_session));
|
|
- if (intf->session == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
- memset(intf->session, 0, sizeof(struct ipmi_session));
|
|
-
|
|
/* setup default LAN maximum request and response sizes */
|
|
intf->max_request_data_size = SERIAL_BM_MAX_RQ_SIZE;
|
|
intf->max_response_data_size = SERIAL_BM_MAX_RS_SIZE;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -285,10 +281,10 @@ serial_bm_open(struct ipmi_intf * intf)
|
|
/* set the new options for the port with flushing */
|
|
tcsetattr(intf->fd, TCSAFLUSH, &ti);
|
|
|
|
- if (intf->session->timeout == 0)
|
|
- intf->session->timeout = SERIAL_BM_TIMEOUT;
|
|
- if (intf->session->retry == 0)
|
|
- intf->session->retry = SERIAL_BM_RETRY_COUNT;
|
|
+ if (intf->ssn_params.timeout == 0)
|
|
+ intf->ssn_params.timeout = SERIAL_BM_TIMEOUT;
|
|
+ if (intf->ssn_params.retry == 0)
|
|
+ intf->ssn_params.retry = SERIAL_BM_RETRY_COUNT;
|
|
|
|
intf->opened = 1;
|
|
|
|
@@ -459,7 +455,7 @@ serial_bm_wait_for_data(struct ipmi_intf * intf)
|
|
pfd.events = POLLIN;
|
|
pfd.revents = 0;
|
|
|
|
- n = poll(&pfd, 1, intf->session->timeout*1000);
|
|
+ n = poll(&pfd, 1, intf->ssn_params.timeout * 1000);
|
|
if (n < 0) {
|
|
lperror(LOG_ERR, "Poll for serial data failed");
|
|
return -1;
|
|
@@ -887,7 +883,7 @@ serial_bm_get_message(struct ipmi_intf * intf,
|
|
tm = clock() - start;
|
|
|
|
tm /= CLOCKS_PER_SEC;
|
|
- } while (tm < intf->session->timeout);
|
|
+ } while (tm < intf->ssn_params.timeout);
|
|
|
|
return 0;
|
|
}
|
|
@@ -910,7 +906,7 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
read_ctx.max_buffer_size = SERIAL_BM_MAX_BUFFER_SIZE;
|
|
|
|
/* Send the message and receive the answer */
|
|
- for (retry = 0; retry < intf->session->retry; retry++) {
|
|
+ for (retry = 0; retry < intf->ssn_params.retry; retry++) {
|
|
/* build output message */
|
|
bridging_level = serial_bm_build_msg(intf, req, msg,
|
|
sizeof (msg), req_ctx, &msg_len);
|
|
@@ -956,7 +952,7 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
/* check if response for inner request is not encapsulated */
|
|
} else if (rv == 1) {
|
|
/* wait for response for inner request */
|
|
- rv = serial_bm_wait_response(intf, &req_ctx[0],
|
|
+ rv = serial_bm_wait_response(intf, &req_ctx[1],
|
|
&read_ctx, msg, sizeof (msg));
|
|
|
|
/* check for IO error */
|
|
@@ -1003,22 +999,14 @@ serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
return NULL;
|
|
}
|
|
|
|
-int
|
|
-serial_bm_set_my_addr(struct ipmi_intf * intf, uint8_t addr)
|
|
-{
|
|
- intf->my_addr = addr;
|
|
- return 0;
|
|
-}
|
|
-
|
|
/*
|
|
* Serial BM interface
|
|
*/
|
|
struct ipmi_intf ipmi_serial_bm_intf = {
|
|
- name: "serial-basic",
|
|
- desc: "Serial Interface, Basic Mode",
|
|
- setup: serial_bm_setup,
|
|
- open: serial_bm_open,
|
|
- close: serial_bm_close,
|
|
- sendrecv: serial_bm_send_request,
|
|
- set_my_addr:serial_bm_set_my_addr
|
|
+ .name = "serial-basic",
|
|
+ .desc = "Serial Interface, Basic Mode",
|
|
+ .setup = serial_bm_setup,
|
|
+ .open = serial_bm_open,
|
|
+ .close = serial_bm_close,
|
|
+ .sendrecv = serial_bm_send_request,
|
|
};
|
|
diff --git a/src/plugins/serial/serial_terminal.c b/src/plugins/serial/serial_terminal.c
|
|
index 34c6fc5..dfcc202 100644
|
|
--- a/src/plugins/serial/serial_terminal.c
|
|
+++ b/src/plugins/serial/serial_terminal.c
|
|
@@ -29,9 +29,11 @@
|
|
* 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.
|
|
*/
|
|
+#define _GNU_SOURCE 1
|
|
|
|
/* Serial Interface, Terminal Mode plugin. */
|
|
|
|
+#include <alloca.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
@@ -225,10 +227,10 @@ ipmi_serial_term_open(struct ipmi_intf * intf)
|
|
/* set the new options for the port with flushing */
|
|
tcsetattr(intf->fd, TCSAFLUSH, &ti);
|
|
|
|
- if (intf->session->timeout == 0)
|
|
- intf->session->timeout = IPMI_SERIAL_TIMEOUT;
|
|
- if (intf->session->retry == 0)
|
|
- intf->session->retry = IPMI_SERIAL_RETRY;
|
|
+ if (intf->ssn_params.timeout == 0)
|
|
+ intf->ssn_params.timeout = IPMI_SERIAL_TIMEOUT;
|
|
+ if (intf->ssn_params.retry == 0)
|
|
+ intf->ssn_params.retry = IPMI_SERIAL_RETRY;
|
|
|
|
intf->opened = 1;
|
|
|
|
@@ -259,7 +261,7 @@ serial_wait_for_data(struct ipmi_intf * intf)
|
|
pfd.events = POLLIN;
|
|
pfd.revents = 0;
|
|
|
|
- n = poll(&pfd, 1, intf->session->timeout*1000);
|
|
+ n = poll(&pfd, 1, intf->ssn_params.timeout*1000);
|
|
if (n < 0) {
|
|
lperror(LOG_ERR, "Poll for serial data failed");
|
|
return -1;
|
|
@@ -357,7 +359,7 @@ recv_response(struct ipmi_intf * intf, unsigned char *data, int len)
|
|
{
|
|
char hex_rs[IPMI_SERIAL_MAX_RESPONSE * 3];
|
|
int i, j, resp_len = 0;
|
|
- unsigned long rv;
|
|
+ long rv;
|
|
char *p, *pp;
|
|
char ch, str_hex[3];
|
|
|
|
@@ -769,7 +771,7 @@ serial_term_get_message(struct ipmi_intf * intf,
|
|
tm = clock() - start;
|
|
|
|
tm /= CLOCKS_PER_SEC;
|
|
- } while (tm < intf->session->timeout);
|
|
+ } while (tm < intf->ssn_params.timeout);
|
|
|
|
return 0;
|
|
}
|
|
@@ -787,7 +789,7 @@ ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
}
|
|
|
|
/* Send the message and receive the answer */
|
|
- for (retry = 0; retry < intf->session->retry; retry++) {
|
|
+ for (retry = 0; retry < intf->ssn_params.retry; retry++) {
|
|
/* build output message */
|
|
bridging_level = serial_term_build_msg(intf, req, msg,
|
|
sizeof (msg), req_ctx, &msg_len);
|
|
@@ -882,33 +884,18 @@ ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
static int
|
|
ipmi_serial_term_setup(struct ipmi_intf * intf)
|
|
{
|
|
- intf->session = malloc(sizeof(struct ipmi_session));
|
|
- if (intf->session == NULL) {
|
|
- lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
- return -1;
|
|
- }
|
|
-
|
|
- memset(intf->session, 0, sizeof(struct ipmi_session));
|
|
-
|
|
/* setup default LAN maximum request and response sizes */
|
|
intf->max_request_data_size = IPMI_SERIAL_MAX_RQ_SIZE;
|
|
intf->max_response_data_size = IPMI_SERIAL_MAX_RS_SIZE;
|
|
- return 0;
|
|
-}
|
|
|
|
-int
|
|
-ipmi_serial_term_set_my_addr(struct ipmi_intf * intf, uint8_t addr)
|
|
-{
|
|
- intf->my_addr = addr;
|
|
return 0;
|
|
}
|
|
|
|
struct ipmi_intf ipmi_serial_term_intf = {
|
|
- name: "serial-terminal",
|
|
- desc: "Serial Interface, Terminal Mode",
|
|
- setup: ipmi_serial_term_setup,
|
|
- open: ipmi_serial_term_open,
|
|
- close: ipmi_serial_term_close,
|
|
- sendrecv: ipmi_serial_term_send_cmd,
|
|
- set_my_addr:ipmi_serial_term_set_my_addr
|
|
+ .name = "serial-terminal",
|
|
+ .desc = "Serial Interface, Terminal Mode",
|
|
+ .setup = ipmi_serial_term_setup,
|
|
+ .open = ipmi_serial_term_open,
|
|
+ .close = ipmi_serial_term_close,
|
|
+ .sendrecv = ipmi_serial_term_send_cmd,
|
|
};
|
|
diff --git a/src/plugins/usb/Makefile.am b/src/plugins/usb/Makefile.am
|
|
new file mode 100644
|
|
index 0000000..2a431f7
|
|
--- /dev/null
|
|
+++ b/src/plugins/usb/Makefile.am
|
|
@@ -0,0 +1,40 @@
|
|
+ #
|
|
+ # Copyright (c) 2015 American Megatrends, Inc.
|
|
+ # All rights reserved.
|
|
+ #
|
|
+ # Redistribution and use in source and binary forms, with or without
|
|
+ # modification,are permitted provided that the following conditions are met:
|
|
+ #
|
|
+ # 1. Redistributions of source code must retain the above copyright notice,
|
|
+ # this list of conditions and the following disclaimer.
|
|
+ #
|
|
+ # 2. Redistributions 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.
|
|
+ #
|
|
+ # 3. Neither the name of the copyright holder nor the names of its contributors
|
|
+ # may be used to endorse or promote products derived from this software
|
|
+ # without specific prior written permission.
|
|
+ #
|
|
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE
|
|
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
+ # POSSIBILITY OF SUCH DAMAGE.
|
|
+ #
|
|
+
|
|
+MAINTAINERCLEANFILES = Makefile.in
|
|
+
|
|
+INCLUDES = -I$(top_srcdir)/include
|
|
+
|
|
+EXTRA_LTLIBRARIES = libintf_usb.la
|
|
+noinst_LTLIBRARIES = @INTF_USB_LIB@
|
|
+libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
|
+libintf_usb_la_SOURCES = usb.c
|
|
+
|
|
diff --git a/src/plugins/usb/usb.c b/src/plugins/usb/usb.c
|
|
new file mode 100644
|
|
index 0000000..2d768de
|
|
--- /dev/null
|
|
+++ b/src/plugins/usb/usb.c
|
|
@@ -0,0 +1,617 @@
|
|
+/*
|
|
+ * Copyright (c) 2015 American Megatrends, Inc.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ *
|
|
+ * 1. Redistributions of source code must retain the above copyright notice,
|
|
+ * this list of conditions and the following disclaimer.
|
|
+ *
|
|
+ * 2. Redistributions 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.
|
|
+ *
|
|
+ * 3. Neither the name of the copyright holder nor the names of its
|
|
+ * contributors may be used to endorse or promote products derived from this
|
|
+ * software without specific prior written permission.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
+ * POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+#define _BSD_SOURCE
|
|
+
|
|
+#include <ipmitool/helper.h>
|
|
+#include <ipmitool/log.h>
|
|
+#include <ipmitool/bswap.h>
|
|
+#include <ipmitool/ipmi.h>
|
|
+#include <ipmitool/ipmi_intf.h>
|
|
+#include <ipmitool/ipmi_oem.h>
|
|
+#include <ipmitool/ipmi_strings.h>
|
|
+#include <ipmitool/ipmi_constants.h>
|
|
+#include <scsi/sg.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <scsi/scsi_ioctl.h>
|
|
+#include <scsi/scsi.h>
|
|
+#include <sys/file.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/types.h>
|
|
+#include <fcntl.h>
|
|
+#include <errno.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#define PACKED __attribute__ ((packed))
|
|
+#define BEGIN_SIG "$G2-CONFIG-HOST$"
|
|
+#define BEGIN_SIG_LEN 16
|
|
+#define MAX_REQUEST_SIZE 64 * 1024
|
|
+#define CMD_RESERVED 0x0000
|
|
+#define SCSI_AMICMD_CURI_WRITE 0xE2
|
|
+#define SCSI_AMICMD_CURI_READ 0xE3
|
|
+#define SCSI_AMIDEF_CMD_SECTOR 0x01
|
|
+#define SCSI_AMIDEF_DATA_SECTOR 0x02
|
|
+#define ERR_SUCCESS 0 /* Success */
|
|
+#define ERR_BIG_DATA 1 /* Too Much Data */
|
|
+#define ERR_NO_DATA 2 /* No/Less Data Available */
|
|
+#define ERR_UNSUPPORTED 3 /* Unsupported Command */
|
|
+#define IN_PROCESS 0x8000 /* Bit 15 of Status */
|
|
+#define SCSI_AMICMD_ID 0xEE
|
|
+
|
|
+/* SCSI Command Packets */
|
|
+typedef struct {
|
|
+ unsigned char OpCode;
|
|
+ unsigned char Lun;
|
|
+ unsigned int Lba;
|
|
+ union {
|
|
+ struct {
|
|
+ unsigned char Reserved6;
|
|
+ unsigned short Length;
|
|
+ unsigned char Reserved9[3];
|
|
+ } PACKED Cmd10;
|
|
+ struct Len32 {
|
|
+ unsigned int Length32;
|
|
+ unsigned char Reserved10[2];
|
|
+ } PACKED Cmd12;
|
|
+ } PACKED CmdLen;
|
|
+} PACKED SCSI_COMMAND_PACKET;
|
|
+
|
|
+typedef struct {
|
|
+ uint8_t byNetFnLUN;
|
|
+ uint8_t byCmd;
|
|
+ uint8_t byData[MAX_REQUEST_SIZE];
|
|
+} PACKED IPMIUSBRequest_T;
|
|
+
|
|
+typedef struct {
|
|
+ uint8_t BeginSig[BEGIN_SIG_LEN];
|
|
+ uint16_t Command;
|
|
+ uint16_t Status;
|
|
+ uint32_t DataInLen;
|
|
+ uint32_t DataOutLen;
|
|
+ uint32_t InternalUseDataIn;
|
|
+ uint32_t InternalUseDataOut;
|
|
+} CONFIG_CMD;
|
|
+
|
|
+static int ipmi_usb_setup(struct ipmi_intf *intf);
|
|
+static struct ipmi_rs *ipmi_usb_send_cmd(struct ipmi_intf *intf,
|
|
+ struct ipmi_rq *req);
|
|
+
|
|
+struct ipmi_intf ipmi_usb_intf = {
|
|
+ .name = "usb",
|
|
+ .desc = "IPMI USB Interface(OEM Interface for AMI Devices)",
|
|
+ .setup = ipmi_usb_setup,
|
|
+ .sendrecv = ipmi_usb_send_cmd,
|
|
+};
|
|
+
|
|
+int
|
|
+scsiProbeNew(int *num_ami_devices, int *sg_nos)
|
|
+{
|
|
+ int inplen = *num_ami_devices;
|
|
+ int numdevfound = 0;
|
|
+ char linebuf[81];
|
|
+ char vendor[81];
|
|
+ int lineno = 0;
|
|
+ FILE *fp;
|
|
+
|
|
+ fp = fopen("/proc/scsi/sg/device_strs", "r");
|
|
+ if (fp == NULL) {
|
|
+ /* Return 1 on error */
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ while (1) {
|
|
+ /* Read line by line and search for "AMI" */
|
|
+ if (fgets(linebuf, 80, fp) == NULL) {
|
|
+ if (fp != NULL) {
|
|
+ fclose(fp);
|
|
+ }
|
|
+ /* Return 1 on error */
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (sscanf(linebuf, "%s", vendor) == 1) {
|
|
+ if (strncmp(vendor, "AMI", strlen("AMI")) == 0) {
|
|
+ numdevfound++;
|
|
+ sg_nos[numdevfound - 1] = lineno;
|
|
+ if (numdevfound == inplen) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ lineno++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *num_ami_devices = numdevfound;
|
|
+ if (fp != NULL) {
|
|
+ fclose(fp);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+OpenCD(struct ipmi_intf *intf, char *CDName)
|
|
+{
|
|
+ intf->fd = open(CDName, O_RDWR);
|
|
+ if (intf->fd == (-1)) {
|
|
+ lprintf(LOG_ERR, "OpenCD:Unable to open device, %s",
|
|
+ strerror(errno));
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+sendscsicmd_SGIO(int cd_desc, unsigned char *cdb_buf, unsigned char cdb_len,
|
|
+ void *data_buf, unsigned int *data_len, int direction,
|
|
+ void *sense_buf, unsigned char slen, unsigned int timeout)
|
|
+{
|
|
+ sg_io_hdr_t io_hdr;
|
|
+
|
|
+ /* Prepare command */
|
|
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
|
|
+ io_hdr.interface_id = 'S';
|
|
+ io_hdr.cmd_len = cdb_len;
|
|
+
|
|
+ /* Transfer direction and length */
|
|
+ io_hdr.dxfer_direction = direction;
|
|
+ io_hdr.dxfer_len = *data_len;
|
|
+
|
|
+ io_hdr.dxferp = data_buf;
|
|
+
|
|
+ io_hdr.cmdp = cdb_buf;
|
|
+
|
|
+ io_hdr.sbp = (unsigned char *)sense_buf;
|
|
+ io_hdr.mx_sb_len = slen;
|
|
+
|
|
+ io_hdr.timeout = timeout;
|
|
+
|
|
+ if (!timeout) {
|
|
+ io_hdr.timeout = 20000;
|
|
+ }
|
|
+
|
|
+ if (ioctl(cd_desc, SG_IO, &io_hdr) < 0) {
|
|
+ lprintf(LOG_ERR, "sendscsicmd_SGIO: SG_IO ioctl error");
|
|
+ return 1;
|
|
+ } else {
|
|
+ if (io_hdr.status != 0) {
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!timeout) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
|
|
+ lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - Not OK");
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - OK");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int
|
|
+AMI_SPT_CMD_Identify(int cd_desc, char *szSignature)
|
|
+{
|
|
+ SCSI_COMMAND_PACKET IdPkt = {0};
|
|
+ int ret;
|
|
+ unsigned int siglen = 10;
|
|
+
|
|
+ IdPkt.OpCode = SCSI_AMICMD_ID;
|
|
+ ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&IdPkt,
|
|
+ 10, szSignature, &siglen, SG_DXFER_FROM_DEV,
|
|
+ NULL, 0, 5000);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int
|
|
+IsG2Drive(int cd_desc)
|
|
+{
|
|
+ char szSignature[15];
|
|
+ int ret;
|
|
+
|
|
+ memset(szSignature, 0, 15);
|
|
+
|
|
+ flock(cd_desc, LOCK_EX);
|
|
+ ret = AMI_SPT_CMD_Identify(cd_desc, szSignature);
|
|
+ flock(cd_desc, LOCK_UN);
|
|
+ if (ret != 0) {
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "IsG2Drive:Unable to send ID command to the device");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (strncmp(szSignature, "$$$AMI$$$", strlen("$$$AMI$$$")) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "IsG2Drive:Signature mismatch when ID command sent");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+FindG2CDROM(struct ipmi_intf *intf)
|
|
+{
|
|
+ int err = 0;
|
|
+ char device[256];
|
|
+ int devarray[8];
|
|
+ int numdev = 8;
|
|
+ int iter;
|
|
+ err = scsiProbeNew(&numdev, devarray);
|
|
+
|
|
+ if (err == 0 && numdev > 0) {
|
|
+ for (iter = 0; iter < numdev; iter++) {
|
|
+ sprintf(device, "/dev/sg%d", devarray[iter]);
|
|
+
|
|
+ if (!OpenCD(intf, device)) {
|
|
+ if (!IsG2Drive(intf->fd)) {
|
|
+ lprintf(LOG_DEBUG, "USB Device found");
|
|
+ return 1;
|
|
+ }
|
|
+ close(intf->fd);
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "Unable to find Virtual CDROM Device");
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+ipmi_usb_setup(struct ipmi_intf *intf)
|
|
+{
|
|
+ if (FindG2CDROM(intf) == 0) {
|
|
+ lprintf(LOG_ERR, "Error in USB session setup \n");
|
|
+ return (-1);
|
|
+ }
|
|
+ intf->opened = 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void
|
|
+InitCmdHeader(CONFIG_CMD *pG2CDCmdHeader)
|
|
+{
|
|
+ memset(pG2CDCmdHeader, 0, sizeof(CONFIG_CMD));
|
|
+ memcpy((char *)pG2CDCmdHeader->BeginSig, BEGIN_SIG, BEGIN_SIG_LEN);
|
|
+}
|
|
+
|
|
+int
|
|
+AMI_SPT_CMD_SendCmd(int cd_desc, char *Buffer, char type, uint16_t buflen,
|
|
+ unsigned int timeout)
|
|
+{
|
|
+ SCSI_COMMAND_PACKET Cmdpkt;
|
|
+ char sensebuff[32];
|
|
+ int ret;
|
|
+ unsigned int pktLen;
|
|
+ int count = 3;
|
|
+
|
|
+ memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
|
|
+
|
|
+ Cmdpkt.OpCode = SCSI_AMICMD_CURI_WRITE;
|
|
+ Cmdpkt.Lba = htonl(type);
|
|
+ Cmdpkt.CmdLen.Cmd10.Length = htons(1);
|
|
+
|
|
+ pktLen = buflen;
|
|
+ while (count > 0) {
|
|
+ ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
|
|
+ 10, Buffer, &pktLen, SG_DXFER_TO_DEV,
|
|
+ sensebuff, 32, timeout);
|
|
+ count--;
|
|
+ if (ret == 0) {
|
|
+ break;
|
|
+ } else {
|
|
+ ret = (-1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int
|
|
+AMI_SPT_CMD_RecvCmd(int cd_desc, char *Buffer, char type, uint16_t buflen)
|
|
+{
|
|
+ SCSI_COMMAND_PACKET Cmdpkt;
|
|
+ char sensebuff[32];
|
|
+ int ret;
|
|
+ unsigned int pktLen;
|
|
+ int count = 3;
|
|
+
|
|
+ memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
|
|
+
|
|
+ Cmdpkt.OpCode = SCSI_AMICMD_CURI_READ;
|
|
+ Cmdpkt.Lba = htonl(type);
|
|
+ Cmdpkt.CmdLen.Cmd10.Length = htons(1);
|
|
+
|
|
+ pktLen = buflen;
|
|
+ while (count > 0) {
|
|
+ ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
|
|
+ 10, Buffer, &pktLen, SG_DXFER_FROM_DEV,
|
|
+ sensebuff, 32, 5000);
|
|
+ count--;
|
|
+ if (0 == ret) {
|
|
+ break;
|
|
+ } else {
|
|
+ ret = (-1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int
|
|
+ReadCD(int cd_desc, char CmdData, char *Buffer, uint32_t DataLen)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = AMI_SPT_CMD_RecvCmd(cd_desc, Buffer, CmdData, DataLen);
|
|
+ if (ret != 0) {
|
|
+ lprintf(LOG_ERR, "Error while reading CD-Drive");
|
|
+ return (-1);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+WriteCD(int cd_desc, char CmdData, char *Buffer, unsigned int timeout,
|
|
+ uint32_t DataLen)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = AMI_SPT_CMD_SendCmd(cd_desc, Buffer, CmdData, DataLen, timeout);
|
|
+ if (ret != 0) {
|
|
+ lprintf(LOG_ERR, "Error while writing to CD-Drive");
|
|
+ return (-1);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+WriteSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
|
|
+ uint32_t NumBytes, uint32_t timeout)
|
|
+{
|
|
+ uint32_t BytesWritten = 0;
|
|
+ int retVal;
|
|
+
|
|
+ if (NumBytes == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ while (BytesWritten < NumBytes) {
|
|
+ if ((retVal = WriteCD(intf->fd, Sector,
|
|
+ (Buffer + BytesWritten),
|
|
+ timeout, NumBytes)) != 0) {
|
|
+ return retVal;
|
|
+ }
|
|
+
|
|
+ BytesWritten += NumBytes;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+ReadSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
|
|
+ uint32_t NumBytes)
|
|
+{
|
|
+ uint32_t BytesRead = 0;
|
|
+
|
|
+ if (NumBytes == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ while (BytesRead < NumBytes) {
|
|
+ if (ReadCD(intf->fd, Sector, (Buffer + BytesRead),
|
|
+ NumBytes) == (-1)) {
|
|
+ return 1;
|
|
+ }
|
|
+ BytesRead += NumBytes;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+WaitForCommandCompletion(struct ipmi_intf *intf, CONFIG_CMD *pG2CDCmdHeader,
|
|
+ uint32_t timeout, uint32_t DataLen)
|
|
+{
|
|
+ uint32_t TimeCounter = 0;
|
|
+
|
|
+ do {
|
|
+ if (ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
+ (char *)(pG2CDCmdHeader), DataLen) == (-1)) {
|
|
+ lprintf(LOG_ERR, "ReadCD returned ERROR");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (pG2CDCmdHeader->Status & IN_PROCESS) {
|
|
+ usleep(1000);
|
|
+ if (timeout > 0) {
|
|
+ TimeCounter++;
|
|
+ if (TimeCounter == (timeout + 1)) {
|
|
+ return 2;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "Command completed");
|
|
+ break;
|
|
+ }
|
|
+ } while (1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+SendDataToUSBDriver(struct ipmi_intf *intf, char *ReqBuffer,
|
|
+ unsigned int ReqBuffLen, unsigned char *ResBuffer,
|
|
+ int *ResBuffLen, unsigned int timeout)
|
|
+{
|
|
+ char CmdHeaderBuffer[sizeof(CONFIG_CMD)];
|
|
+ int retVal;
|
|
+ int waitretval = 0;
|
|
+ unsigned int to = 0;
|
|
+ uint32_t DataLen = 0;
|
|
+
|
|
+ CONFIG_CMD *pG2CDCmdHeader = (CONFIG_CMD *)CmdHeaderBuffer;
|
|
+
|
|
+ /* FillHeader */
|
|
+ InitCmdHeader(pG2CDCmdHeader);
|
|
+
|
|
+ /* Set command number */
|
|
+ pG2CDCmdHeader->Command = CMD_RESERVED;
|
|
+
|
|
+ /* Fill Lengths */
|
|
+ pG2CDCmdHeader->DataOutLen = *ResBuffLen;
|
|
+ pG2CDCmdHeader->DataInLen = ReqBuffLen;
|
|
+
|
|
+ if (!timeout) {
|
|
+ to = 3000;
|
|
+ }
|
|
+
|
|
+ DataLen = sizeof(CONFIG_CMD);
|
|
+
|
|
+ if (WriteCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
+ (char *)(pG2CDCmdHeader), to, DataLen) == (-1)) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in Write CD of SCSI_AMIDEF_CMD_SECTOR");
|
|
+ return (-1);
|
|
+ }
|
|
+
|
|
+ /* Write the data to hard disk */
|
|
+ if ((retVal = WriteSplitData(intf, ReqBuffer,
|
|
+ SCSI_AMIDEF_DATA_SECTOR,
|
|
+ ReqBuffLen, timeout)) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in WriteSplitData of SCSI_AMIDEF_DATA_SECTOR");
|
|
+ return (-1);
|
|
+ }
|
|
+
|
|
+ if (!timeout) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* Read Status now */
|
|
+ waitretval = WaitForCommandCompletion(intf, pG2CDCmdHeader, timeout,
|
|
+ DataLen);
|
|
+ if (waitretval != 0) {
|
|
+ lprintf(LOG_ERR, "WaitForCommandComplete failed");
|
|
+ return (0 - waitretval);
|
|
+ } else {
|
|
+ lprintf(LOG_DEBUG, "WaitForCommandCompletion SUCCESS");
|
|
+ }
|
|
+
|
|
+ switch (pG2CDCmdHeader->Status) {
|
|
+ case ERR_SUCCESS:
|
|
+ *ResBuffLen = pG2CDCmdHeader->DataOutLen;
|
|
+ lprintf(LOG_DEBUG, "Before ReadSplitData %x", *ResBuffLen);
|
|
+ if (ReadSplitData(intf, (char *)ResBuffer,
|
|
+ SCSI_AMIDEF_DATA_SECTOR,
|
|
+ pG2CDCmdHeader->DataOutLen) != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Err ReadSplitData SCSI_AMIDEF_DATA_SCTR");
|
|
+ return (-1);
|
|
+ }
|
|
+ /* Additional read to see verify there was not problem
|
|
+ * with the previous read
|
|
+ */
|
|
+ DataLen = sizeof(CONFIG_CMD);
|
|
+ ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
|
|
+ (char *)(pG2CDCmdHeader), DataLen);
|
|
+ break;
|
|
+ case ERR_BIG_DATA:
|
|
+ lprintf(LOG_ERR, "Too much data");
|
|
+ break;
|
|
+ case ERR_NO_DATA:
|
|
+ lprintf(LOG_ERR, "Too little data");
|
|
+ break;
|
|
+ case ERR_UNSUPPORTED:
|
|
+ lprintf(LOG_ERR, "Unsupported command");
|
|
+ break;
|
|
+ default:
|
|
+ lprintf(LOG_ERR, "Unknown status");
|
|
+ }
|
|
+
|
|
+ return pG2CDCmdHeader->Status;
|
|
+}
|
|
+
|
|
+static struct ipmi_rs *
|
|
+ipmi_usb_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
|
+{
|
|
+ static struct ipmi_rs rsp;
|
|
+ long timeout = 20000;
|
|
+ uint8_t byRet = 0;
|
|
+ char ReqBuff[MAX_REQUEST_SIZE] = {0};
|
|
+ IPMIUSBRequest_T *pReqPkt = (IPMIUSBRequest_T *)ReqBuff;
|
|
+ int retries = 0;
|
|
+ /********** FORM IPMI PACKET *****************/
|
|
+ pReqPkt->byNetFnLUN = req->msg.netfn << 2;
|
|
+ pReqPkt->byNetFnLUN += req->msg.lun;
|
|
+ pReqPkt->byCmd = req->msg.cmd;
|
|
+ if (req->msg.data_len) {
|
|
+ memcpy(pReqPkt->byData, req->msg.data, req->msg.data_len);
|
|
+ }
|
|
+
|
|
+ /********** SEND DATA TO USB ******************/
|
|
+ while (retries < 3) {
|
|
+ retries++;
|
|
+ byRet = SendDataToUSBDriver(intf, ReqBuff,
|
|
+ 2 + req->msg.data_len, rsp.data,
|
|
+ &rsp.data_len,timeout);
|
|
+
|
|
+ if (byRet == 0) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (retries == 3) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error while sending command using",
|
|
+ "SendDataToUSBDriver");
|
|
+ rsp.ccode = byRet;
|
|
+ return &rsp;
|
|
+ }
|
|
+
|
|
+ rsp.ccode = rsp.data[0];
|
|
+
|
|
+ /* Save response data for caller */
|
|
+ if ((rsp.ccode == 0) && (rsp.data_len > 0)) {
|
|
+ memmove(rsp.data, rsp.data + 1, rsp.data_len - 1);
|
|
+ rsp.data[rsp.data_len] = 0;
|
|
+ rsp.data_len -= 1;
|
|
+ }
|
|
+ return &rsp;
|
|
+}
|