diff options
87 files changed, 8212 insertions, 3154 deletions
@@ -1,3 +1,152 @@ +version 1.8.16 2015-11-22 + * Add _ipmi_get_channel_access() and _ipmi_get_channel_info() + * Add _ipmi_get_user_access() and _ipmi_set_user_access() + * Add _ipmi_get_user_name() + * Add _ipmi_set_channel_access() function + * Add _ipmi_set_user_password() function + * Add limits check in get_cmdline_macaddr() + * Change expression in ipmi_pef_get_info() in order to silence Coverity + * Change expression in ipmi_pef_list_policies() in order to silence Coverity + * Code cleanup in ipmi_user_main() + * Create ask_password() and re-use code + * Delete dead code from ipmi_sunoem_echo() - CID#1261338 + * Don't output pidfile before parsing command line arguments + * Don't use tmp variable since it's not necessary in ipmi_user_test() + * Fix 'user help' output + * Fix Assign instead of compare in KfwumGetDeviceInfo() - CID#1149034 + * Fix Identical code for different branches in ipmi_tsol_main() - + CID#1261346 + * Fix big parameter passed by value in ipmi_sel_oem_match() - CID#1261347 + * Fix dead code in ipmi_firewall_reset() - CID#1261342 + * Fix eval logic in ipmi_user_priv() + * Fix file descriptor leak in ipmi_exec_main() - CID#1149040 + * Fix identical code for diff branches in DellOEM - CID#1261326 + * Fix memory leak in get_supermicro_evt_desc() + * Fix memory leak in ipmi_ek_display_board_info_area() - CID#1149051 + * Fix missing return in ipmi_kontronoem_main() - CID#1261317 + * Fix of previous commit - memset() expects pointer + * Fix out-of-bound-reads in get_supermicro_evt_desc() + * Fix resource leak in fru_area_print_board() - CDI#1149048 + * Fix resource leak in fru_area_print_chassis() - CID#1149047 + * Fix resource leak in fru_area_print_product() - CID#1149046 + * Fix resource leak in ipmi_kontron_set_serial_number() - CID#1149041 + * Fix typo vlan->VLAN in ipmi_lan_set_vlan_id() and + ipmi_lan_set_vlan_priority() + * Fix uninitialized struct in ipmi_fru_upg_ekeying() - CID#1149065 + * Fix user input validation in Channel and User sub-commands + * Fix wrong size argument in ipmi_sdr_list_cache_fromfile() - CID#1149056 + * Fix/remove pointer cast in _ipmi_set_user_access() + * Hook functions in ipmi_user to _ipmi_set_user_password() + * Hook ipmi_get_channel_info() to _ipmi_get_*() + * Hook ipmi_get_channel_medium() to new _ipmi_get_*() functions + * Hook ipmi_lan_set_password() to _ipmi_set_user_password() + * Hook ipmi_print_user_list() and friends to _ipmi_* functions + * Hook ipmi_set_alert_enable() to _ipmi_*() + * Hook ipmi_set_user_access() to _ipmi_set_user_access() + * Hook ipmi_user_priv() to _ipmi_set_user_access() + * ID:307 - Intel I82751 super pass through mode fixup + * ID:355 - Fix compiler warnings for Dummy Interface + * ID:380 - raw commands override retry and timeout values + * ID:319 - Interface safe re-open + * ID:320 - Add VITA 46.11 support + * ID:333 - Set read timeout to 15s in OpenIPMI interface + * ID:336 - ipmitool does not fall back to IPv4 for IPMI v2 / RMCP+ sessions + * ID:343 - Print actual sensor thresholds in 'sensors' comand + * ID:343 - Remove AC_FUNC_MALLOC + * ID:344 - Fix HPM.2 long message support + * ID:345 - Do not do several close session retries when catching SIGINT + * ID:346 - lib/ipmi_sdradd.c ipmi_sdr_read_record has a file descriptor leak + * ID:347 - Incorrect reserved channel number + * ID:348 - Add support for the "System Firmware Version" + * ID:349 - user set password - add option to choose 16/20 byte password + * ID:354 - Replace obsolete u_int with uint32_t in dimm_spd.c + * ID:354 - Replace obsolete u_int[0-9]+_t with standardized types in Free + iface + * ID:354 - forcefully switch to C99 and more strict CFLAGS + * ID:354 - replace/drop caddr_t in IMB + * ID:354 - struct member h_addr has been replaced + * ID:354 - uint8_t >= 0 is always true, don't test it + * ID:355 - Fix Enumeration value not handled in ipmi_get_event_desc() + * ID:355 - Fix ``ISO C forbids omitting the middle term of a ?: expression'' + * ID:355 - Fix ``obsolete use of designated initializer with ¿:¿'' warning + * ID:355 - Fix comparison of unsigned expression + * ID:355 - Fix compiler warnings + * ID:355 - Fix compiler warnings in dimm_spd.c + * ID:355 - Fix couple compiler warnings in ipmi_lanp.h + * ID:355 - Fix formatting warning in get_cmdline_ipaddr() + * ID:355 - Fix zero-length format string warning in + get_supermicro_evt_desc() + * ID:355 - Remove defined but unused variable in _set_command_enables() + * ID:355 - remove unused variables from ipmi_dcmi.c + * ID:357 - out-of-bound access in DDR4 code ID:356 - DIMM4 Die Count is + unreachable + * ID:357 - out-of-bound access in DDR4 code + * ID:358 - check data length in else branch of ipmi_spd_print() + * ID:361 - Add a OEM IANA information + * ID:363 - Node Manager feature patch. + * ID:363 - fix Coverity issues in NM implementation + * ID:364 - Fix for serial-basic interface bridging + * ID:365 - Fix for ipmitool crash when using serial-terminal interface + * ID:366 - Properly clean LAN and LAN+ interfaces on close + * ID:367 - Fix building of non-bridged LAN interface commands + * ID:368 - Fix handling of bridging-related parameters + * ID:369 - Fix lanplus interface bridging and response matching + * ID:370 - add anonymous union support in CFLAGS for older gcc + * ID:371 - add ericsson oem + * ID:373 - Fix compilation of IMB on Windows + * ID:374 - Check/set LED Duration correctly + * ID:376 - Add means to configure "Bad Password Threshold" + * ID:381 - Script to log installation status as SEL events + * ID:382 - Fix memcpy() params in HpmFwupgActionUploadFirmware() + * ID:383 - Fix compile-time error in src/plugins/lan/lan.c + * ID:384 - Fix compilation under cygwin64 + * ID:388 - Fix Error message always printed if BMC does not support VITA + * ID:388 - Handle ccode 0xCC as well in VITA discovery + * ID:388 - Turn all messages into LOG_INFO in VITA discovery + * ID:389 - Add on of Advantech IANA number + * ID:390 - Support for new Communication Interface (USB Medium) + * ID:391 - changing data_len from 17 to 16 according to ipmi spec 22.29, + first byte is completion code + * ID:392 - _ipmi_get_user_name() work-around for some BMCs + * ID:393 - ipmitool man page addition for Node Manager support. + * ID:394 - close fp if isn't NULL and set it NULL afterwards in USB plugin + * ID:394 - plugins/usb: Fix probe for SCSI devices + * ID:395 - Fix fru string without resizing it + * ID:396 - Fixed invalid length check in picmg led cap command. + * ID:397 - Fixed picmg policy set command. + * ID:398 - Fixed channel setaccess command. + * ID:399 - Fixed channel getciphers command. + * ID:401 - Fixed 30 second delay when activating SOL on 'dumb' Intel MACs. + * ID:402 - Misguiding error print-out when using some 'lan' commands. + * Init user_access_t struct in ipmi_user_priv() + * Make user User Privilege Limit is within range + * Node Manager Feature, correct 1268194 missing break. + * Output pidfile only in verbose mode + * Print error message to STDERR in ipmi_channel.c + * Re-work 'channel getaccess' and 'channel setaccess' + * Re-work ccode eval in ipmi_get_channel_medium() + * Remove commented-out code in ipmi_picmg_clk_set() - CID#1261339 + * Remove dead code - rsp can't be NULL at this point - CID#1149005 + * Remove dead code in fru_area_print_board() - CID#1149001 + * Remove dead code in fru_area_print_chassis() - CID#1149000 + * Remove dead code in fru_area_print_product() - CID#1148999 + * Remove dead(duplicate) code from ipmi_sol_main() - CID#1148996 + * Remove get_channel_access_rsp and get_channel_info_rsp structs + * Remove ipmi_user_set_password() + * Remove length checks in get_supermicro_evt_desc() + * Remove redundant user-input conversion from ipmi_sel_delete() + * Remove trailing white-spaces in ipmi_user.c + * Remove trailing white-spaces in ipmi_user.c + * Remove trailing white-spaces in src/plugins/dummy/dummy.c + * Remove unused variable from ipmi_get_channel_cipher_suites() + * Replace deprecated bzero() with memset() + * Replace s6_addr16 with s6_addr since Mac OS X does not have it + * Rewrite ipmi_set_channel_access() + * Split ipmi_user_main() into smaller functions + * ipmi_print_user_summary() to utilize _ipmi_get_user_access() + * ipmitool delloem: ipmitool delloem extension always return success - fix + it + version 1.8.15 2014-11-24 * ID: 340 - ipmitool sol session improperly closes on packet retry * ID: 277 - support for hostnames longer than 64 chars diff --git a/Makefile.in b/Makefile.in index 1f4d712..ad62af7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -274,6 +274,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/config.h.in b/config.h.in index a625bca..dc91f49 100644 --- a/config.h.in +++ b/config.h.in @@ -54,10 +54,6 @@ /* Define to 1 if you have the <linux/compiler.h> header file. */ #undef HAVE_LINUX_COMPILER_H -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE @@ -185,6 +181,9 @@ /* Define to 1 to enable serial interface. */ #undef IPMI_INTF_SERIAL +/* Define to 1 to enable USB interface. */ +#undef IPMI_INTF_USB + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR @@ -245,6 +244,3 @@ #ifndef __cplusplus #undef inline #endif - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc @@ -652,6 +652,8 @@ INTF_SERIAL_LIB INTF_SERIAL INTF_LANPLUS_LIB INTF_LANPLUS +INTF_USB_LIB +INTF_USB INTF_LAN_LIB INTF_LAN BASEDIR @@ -675,8 +677,8 @@ DUMPBIN LD FGREP LIBTOOL -POW_LIB LIBOBJS +POW_LIB EGREP GREP CPP @@ -793,6 +795,7 @@ enable_libtool_lock enable_solaris_opt enable_internal_md5 enable_intf_lan +enable_intf_usb enable_intf_lanplus enable_intf_serial with_kerneldir @@ -1448,6 +1451,7 @@ Optional Features: --enable-solaris-opt enable all options for Solaris [default=no] --enable-internal-md5 enable internal MD5 library [default=no] --enable-intf-lan enable IPMIv1.5 LAN interface [default=yes] + --enable-intf-usb enable IPMI USB interface [default=yes] --enable-intf-lanplus enable IPMIv2.0 RMCP+ LAN interface [default=auto] --enable-intf-serial enable direct Serial Basic/Terminal mode interface [default=yes] @@ -2893,7 +2897,7 @@ fi # Define the identity of the package. PACKAGE=ipmitool - VERSION=1.8.15 + VERSION=1.8.16 cat >>confdefs.h <<_ACEOF @@ -4935,73 +4939,6 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h esac -for ac_header in stdlib.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" -if test "x$ac_cv_header_stdlib_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_STDLIB_H 1 -_ACEOF - -fi - -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 -$as_echo_n "checking for GNU libc compatible malloc... " >&6; } -if ${ac_cv_func_malloc_0_nonnull+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_func_malloc_0_nonnull=no -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#if defined STDC_HEADERS || defined HAVE_STDLIB_H -# include <stdlib.h> -#else -char *malloc (); -#endif - -int -main () -{ -return ! malloc (0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_malloc_0_nonnull=yes -else - ac_cv_func_malloc_0_nonnull=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 -$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } -if test $ac_cv_func_malloc_0_nonnull = yes; then : - -$as_echo "#define HAVE_MALLOC 1" >>confdefs.h - -else - $as_echo "#define HAVE_MALLOC 0" >>confdefs.h - - case " $LIBOBJS " in - *" malloc.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS malloc.$ac_objext" - ;; -esac - - -$as_echo "#define malloc rpl_malloc" >>confdefs.h - -fi - - for ac_header in sys/select.h sys/socket.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -5226,7 +5163,7 @@ fi done -CFLAGS="$CFLAGS -fno-strict-aliasing -Wreturn-type" +CFLAGS="$CFLAGS -Wall -Wextra -std=c99 -pedantic -Wformat -Wformat-nonliteral" case `pwd` in *\ * | *\ *) @@ -12621,6 +12558,7 @@ fi 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 @@ -12698,6 +12636,39 @@ $as_echo "#define ENABLE_ALL_OPTIONS 1" >>confdefs.h fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdio.h> + +int +main () +{ + + struct test { + union { + int a; + unsigned int b; + }; + } test; + + printf("a is %d", test.a); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_need_fms_extension=no +else + ac_need_fms_extension=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if test "x$ac_need_fms_extension" = "xyes"; then + CFLAGS="$CFLAGS -fms-extensions" + +fi + # Check whether --enable-internal-md5 was given. if test "${enable_internal_md5+set}" = set; then : enableval=$enable_internal_md5; xenable_internal_md5=$enableval @@ -12870,6 +12841,27 @@ $as_echo "#define IPMI_INTF_LAN 1" >>confdefs.h IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la" fi +# Check whether --enable-intf-usb was given. +if test "${enable_intf_usb+set}" = set; then : + enableval=$enable_intf_usb; xenable_intf_usb=$enableval +else + xenable_intf_usb=yes +fi + +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 + +$as_echo "#define IPMI_INTF_USB 1" >>confdefs.h + + INTF_USB=usb + + INTF_USB_LIB=libintf_usb.la + + IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la" +fi + # Check whether --enable-intf-lanplus was given. if test "${enable_intf_lanplus+set}" = set; then : enableval=$enable_intf_lanplus; xenable_intf_lanplus=$enableval @@ -13941,7 +13933,7 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_config_files="$ac_config_files Makefile doc/Makefile contrib/Makefile control/Makefile control/pkginfo control/prototype control/rpmmacros control/ipmitool.spec lib/Makefile include/Makefile include/ipmitool/Makefile src/Makefile src/plugins/Makefile src/plugins/lan/Makefile src/plugins/lanplus/Makefile src/plugins/open/Makefile src/plugins/free/Makefile src/plugins/imb/Makefile src/plugins/bmc/Makefile src/plugins/lipmi/Makefile src/plugins/serial/Makefile src/plugins/dummy/Makefile" +ac_config_files="$ac_config_files Makefile doc/Makefile contrib/Makefile control/Makefile control/pkginfo control/prototype control/rpmmacros control/ipmitool.spec lib/Makefile include/Makefile include/ipmitool/Makefile src/Makefile src/plugins/Makefile src/plugins/lan/Makefile src/plugins/lanplus/Makefile src/plugins/open/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" cat >confcache <<\_ACEOF @@ -14968,6 +14960,7 @@ do "src/plugins/free/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/free/Makefile" ;; "src/plugins/imb/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/imb/Makefile" ;; "src/plugins/bmc/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/bmc/Makefile" ;; + "src/plugins/usb/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/usb/Makefile" ;; "src/plugins/lipmi/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/lipmi/Makefile" ;; "src/plugins/serial/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/serial/Makefile" ;; "src/plugins/dummy/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/dummy/Makefile" ;; @@ -16348,6 +16341,8 @@ $as_echo " free : $xenable_intf_free" >&6; } $as_echo " imb : $xenable_intf_imb" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: bmc : $xenable_intf_bmc" >&5 $as_echo " bmc : $xenable_intf_bmc" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: usb : $xenable_intf_usb" >&5 +$as_echo " usb : $xenable_intf_usb" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: lipmi : $xenable_intf_lipmi" >&5 $as_echo " lipmi : $xenable_intf_lipmi" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: serial : $xenable_intf_serial" >&5 diff --git a/configure.ac b/configure.ac index 4c07d47..a1bcf38 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl autoconf for ipmitool dnl AC_INIT([src/ipmitool.c]) AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE([ipmitool], [1.8.15]) +AM_INIT_AUTOMAKE([ipmitool], [1.8.16]) AM_CONFIG_HEADER(config.h) AC_CONFIG_SRCDIR([src/ipmitool.c]) AC_PREREQ(2.50) @@ -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/Makefile.in b/contrib/Makefile.in index bd77fb7..868dd15 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -222,6 +222,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -321,7 +323,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/control/Makefile.in b/control/Makefile.in index ca71b35..3c1ae92 100644 --- a/control/Makefile.in +++ b/control/Makefile.in @@ -193,6 +193,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/doc/Makefile.in b/doc/Makefile.in index fec28ea..fb184ec 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -223,6 +223,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/include/Makefile.in index 3b5ab4c..023ae85 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -251,6 +251,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/include/ipmitool/Makefile.in index a45e1bf..cf46c1f 100644 --- a/include/ipmitool/Makefile.in +++ b/include/ipmitool/Makefile.in @@ -212,6 +212,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -315,7 +317,7 @@ 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 all: all-am 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..67f6019 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,11 @@ struct ipmi_intf { int abort; int noanswer; int picmg_avail; + int vita_avail; IPMI_OEM manufacturer_id; + int ai_family; + 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/ipmitool.spec b/ipmitool.spec index 1b30927..749e82d 100644 --- a/ipmitool.spec +++ b/ipmitool.spec @@ -1,6 +1,6 @@ Name: ipmitool Summary: ipmitool - Utility for IPMI control -Version: 1.8.15 +Version: 1.8.16 Release: 1%{?_distro:.%{_distro}} License: BSD Group: Utilities 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/Makefile.in b/lib/Makefile.in index 96e8ae8..5c993cb 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -130,7 +130,7 @@ am_libipmitool_la_OBJECTS = helper.lo ipmi_sdr.lo ipmi_sel.lo \ ipmi_tsol.lo ipmi_firewall.lo ipmi_kontronoem.lo \ ipmi_hpmfwupg.lo ipmi_sdradd.lo ipmi_ekanalyzer.lo \ ipmi_gendev.lo ipmi_ime.lo ipmi_delloem.lo ipmi_dcmi.lo \ - hpm2.lo md5.lo + hpm2.lo ipmi_vita.lo md5.lo libipmitool_la_OBJECTS = $(am_libipmitool_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -253,6 +253,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -357,7 +359,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 @@ -452,6 +454,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sunoem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_tsol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_user.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_vita.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@ 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) { @@ -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..5171644 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; - } - - memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); + struct channel_info_t channel_info = {0}; + int ccode = 0; - 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 = 2; 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[2], &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,6 +2000,1578 @@ ipmi_dcmi_pwr_actdeact(struct ipmi_intf * intf, uint8_t option) } /* end power management activate/deactivate */ +/* 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 + * + * This function returns the available capabilities of the platform. + * + * returns success/failure + * + * @intf: ipmi interface handler + * @caps: fills in capability struct + */ +static int +_ipmi_nm_getcapabilities(struct ipmi_intf * intf, uint8_t domain, uint8_t trigger, struct nm_capability *caps) +{ + 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] = 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; + } + memcpy(caps, rsp->data, sizeof (struct nm_capability)); + return 0; +} + +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; + } + 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; + } + 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; + } + /* 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; + } + } + 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); + + break; + default: + print_strs(dcmi_thermalpolicy_vals, + "thermalpolicy <command>", + LOG_ERR, 0); + return -1; + } + return rc; +} + /* main * * @intf: dcmi interface handler @@ -1741,14 +3582,13 @@ int ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) { int rc = 0; - uint8_t ctl = 0; - int i, ii, instances; + 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", - -1, 0); + LOG_ERR, 0); return -1; } /* start the cmd requested */ @@ -1757,7 +3597,7 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) /* 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", + lprintf(LOG_ERR,"Error discovering %s capabilities!\n", val2str2(i, dcmi_capable_vals)); return -1; } @@ -1768,142 +3608,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) argv++; if (argv[0] == NULL) { print_strs(dcmi_pwrmgmt_vals, "power <command>", - -1, 0); + LOG_ERR, 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; - - 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 */ + rc = ipmi_dcmi_parse_power(intf, argc, argv); break; /* end power command */ case 0x02: @@ -1933,10 +3641,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) if (argc == 1 ) { print_strs(dcmi_cmd_vals, "Data Center Management Interface commands", - -1, 0); + LOG_ERR, 0); return -1; } - if (ipmi_dcmi_prnt_setassettag(intf, argv[1]) < 0) { + if (ipmi_dcmi_prnt_setassettag(intf, (uint8_t *)argv[1]) < 0) { lprintf(LOG_ERR, "\nError setting asset tag!"); return -1; } @@ -1958,10 +3666,10 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) if (argc == 1 ) { print_strs(dcmi_cmd_vals, "Data Center Management Interface commands", - -1, 0); + LOG_ERR, 0); return -1; } - if (ipmi_dcmi_prnt_setmngctrlids(intf, argv[1]) < 0) { + if (ipmi_dcmi_prnt_setmngctrlids(intf, (uint8_t *)argv[1]) < 0) { lprintf(LOG_ERR, "Error setting management controller identifier string!"); return -1; @@ -1970,110 +3678,21 @@ ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char **argv) } /* 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 -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); - - break; - default: - print_strs(dcmi_thermalpolicy_vals, - "thermalpolicy <command>", - -1, 0); - return -1; - } + /* 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..40f98e7 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; @@ -4775,13 +4772,12 @@ f_type, uint8_t f_index, char *f_string) checksum = 0; /* Calculate Header Checksum */ - for( i = header_offset; i < header_offset - + fru_section_len - 1; i ++ ) + for (i = 0; i < fru_section_len - 1; i++) { checksum += fru_data[i]; } checksum = (~checksum) + 1; - fru_data[header_offset + fru_section_len - 1] = checksum; + fru_data[fru_section_len - 1] = checksum; /* Write the updated section to the FRU data; source offset => 0 */ if( write_fru_area(intf, &fru, fruId, 0, @@ -4850,8 +4846,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..ecd313a 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>]"); } @@ -2299,8 +2451,6 @@ ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv) return 0; } - chan = find_lan_channel(intf, 1); - if (strncmp(argv[0], "printconf", 9) == 0 || strncmp(argv[0], "print", 5) == 0) { @@ -2312,6 +2462,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 +2483,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..a752b59 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> @@ -74,9 +75,9 @@ #endif #ifdef ENABLE_ALL_OPTIONS -# define OPTION_STRING "I:hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:" +# define OPTION_STRING "I:46hVvcgsEKYao:H:d:P:f:U:p:C:L:A:t:T:m:z:S:l:b:B:e:k:y:O:R:N:D:" #else -# define OPTION_STRING "I:hVvcH:f:U:p:d:S:D:" +# define OPTION_STRING "I:46hVvcH:f:U:p:d:S:D:" #endif extern int verbose; @@ -227,6 +228,8 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ lprintf(LOG_NOTICE, " -S sdr Use local file for remote SDR cache"); lprintf(LOG_NOTICE, " -D tty:b[:s] Specify the serial device, baud rate to use"); lprintf(LOG_NOTICE, " and, optionally, specify that interface is the system one"); + lprintf(LOG_NOTICE, " -4 Use only IPv4"); + lprintf(LOG_NOTICE, " -6 Use only IPv6"); #ifdef ENABLE_ALL_OPTIONS lprintf(LOG_NOTICE, " -a Prompt for remote password"); lprintf(LOG_NOTICE, " -Y Prompt for the Kg key for IPMIv2 authentication"); @@ -263,13 +266,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 +344,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 @@ -385,6 +403,7 @@ ipmi_main(int argc, char ** argv, int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */ int argflag, i, found; int rc = -1; + int ai_family = AF_UNSPEC; char sol_escape_char = SOL_ESCAPE_CHARACTER_DEFAULT; char * devfile = NULL; @@ -610,6 +629,38 @@ ipmi_main(int argc, char ** argv, goto out_free; } break; + case '4': + /* IPv4 only */ + if (ai_family == AF_UNSPEC) { + ai_family = AF_INET; + } else { + if (ai_family == AF_INET6) { + lprintf(LOG_ERR, + "Parameter is mutually exclusive with -6."); + } else { + lprintf(LOG_ERR, + "Multiple -4 parameters given."); + } + rc = (-1); + goto out_free; + } + break; + case '6': + /* IPv6 only */ + if (ai_family == AF_UNSPEC) { + ai_family = AF_INET6; + } else { + if (ai_family == AF_INET) { + lprintf(LOG_ERR, + "Parameter is mutually exclusive with -4."); + } else { + lprintf(LOG_ERR, + "Multiple -6 parameters given."); + } + rc = (-1); + goto out_free; + } + break; #ifdef ENABLE_ALL_OPTIONS case 'o': if (oemtype) { @@ -893,6 +944,7 @@ ipmi_main(int argc, char ** argv, /* setup device file if given */ ipmi_main_intf->devfile = devfile; + ipmi_main_intf->ai_family = ai_family; /* Open the interface with the specified or default IPMB address */ ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR; if (ipmi_main_intf->open != NULL) { @@ -900,15 +952,26 @@ ipmi_main(int argc, char ** argv, goto out_free; } } - /* - * Attempt picmg 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 (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) { + /* + * 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)) { + 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 if (!ipmi_oem_active(ipmi_main_intf, "i82571spt")) { + 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 +979,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 +1028,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..f47577e 100644 --- a/lib/ipmi_picmg.c +++ b/lib/ipmi_picmg.c @@ -417,27 +417,6 @@ is_led_color(const char *argv_ptr, uint8_t *led_color_ptr) lprintf(LOG_ERR, "LED Color must be from ranges: <1..6>, <0xE..0xF>"); return (-1); } -/* is_led_duration - wrapper to convert user input into integer. - * LED duration range is <1..127> - * - * @argv_ptr: source string to convert from; usually argv - * @enable_ptr: pointer where to store result - * returns: zero on success, other values mean error - */ -int -is_led_duration(const char *argv_ptr, uint8_t *led_duration_ptr) -{ - if (!argv_ptr || !led_duration_ptr) { - lprintf(LOG_ERR, "is_led_duration(): invalid argument(s)."); - return (-1); - } - if (str2uchar(argv_ptr, led_duration_ptr) == 0 - && *led_duration_ptr > 0 && *led_duration_ptr <= 127) { - return 0; - } - lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv_ptr); - return (-1); -} /* is_led_function - wrapper to convert user input into integer. * LED functions, however, might differ by OEM: * - 0x00 - off override @@ -772,21 +751,19 @@ ipmi_picmg_fru_activation_policy_set(struct ipmi_intf * intf, int argc, char ** if (is_fru_id(argv[0], &msg_data[1]) != 0) { return (-1); } - if (str2uchar(argv[1], &msg_data[2]) != 0 || msg_data[2] > 1) { + if (str2uchar(argv[1], &msg_data[2]) != 0 || msg_data[2] > 3) { /* FRU Lock Mask */ lprintf(LOG_ERR, "Given FRU Lock Mask '%s' is invalid.", argv[1]); return (-1); } - if (str2uchar(argv[2], &msg_data[3]) != 0 || msg_data[3] > 1) { + if (str2uchar(argv[2], &msg_data[3]) != 0 || msg_data[3] > 3) { /* FRU Act Policy */ lprintf(LOG_ERR, "Given FRU Activation Policy '%s' is invalid.", argv[2]); return (-1); } - msg_data[2]&= 0x03; - msg_data[3]&= 0x03; rsp = intf->sendrecv(intf, &req); @@ -1363,19 +1340,55 @@ ipmi_picmg_set_led_state(struct ipmi_intf * intf, int argc, char ** argv) memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; - req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; - req.msg.data = msg_data; + req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; + req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ if (is_fru_id(argv[0], &msg_data[1]) != 0 || is_led_id(argv[1], &msg_data[2]) != 0 || is_led_function(argv[2], &msg_data[3]) != 0 - || is_led_duration(argv[3], &msg_data[4]) != 0 || is_led_color(argv[4], &msg_data[5]) != 0) { return (-1); } + /* Validating the LED duration is not as simple as the other arguments, as + * the range of valid durations depends on the LED function. From the spec: + * + * ``On-duration: LED on-time in tens of milliseconds if (1 <= Byte 4 <= FAh) + * Lamp Test time in hundreds of milliseconds if (Byte 4 = FBh). Lamp Test + * time value must be less than 128. Other values when Byte 4 = FBh are + * reserved. Otherwise, this field is ignored and shall be set to 0h.'' + * + * If we're doing a lamp test, then the allowed values are 0 -> 127. + * Otherwise, the allowed values are 0 -> 255. However, if the function is + * not a lamp test (0xFB) and outside the range 0x01 -> 0xFA then the value + * should be set to 0. + * + * Start by checking we have a parameter. + */ + if (!argv[3]) { + lprintf(LOG_ERR, "LED Duration: invalid argument(s)."); + return (-1); + } + /* Next check we have a number. */ + if (str2uchar(argv[3], &msg_data[4]) != 0) { + lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv[3]); + return (-1); + } + /* If we have a lamp test, ensure it's not too long a duration. */ + if (msg_data[3] == 0xFB && msg_data[4] > 127) { + lprintf(LOG_ERR, "Given LED Duration '%s' is invalid", argv[3]); + return (-1); + } + /* If we're outside the range that allows durations, set the duration to 0. + * Warn the user that we're doing this. + */ + if (msg_data[4] != 0 && (msg_data[3] == 0 || msg_data[3] > 0xFB)) { + lprintf(LOG_WARN, "Setting LED Duration '%s' to '0'", argv[3]); + msg_data[4] = 0; + } + rsp = intf->sendrecv(intf, &req); if (!rsp) { @@ -1745,18 +1758,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; @@ -2137,8 +2140,8 @@ ipmi_picmg_main (struct ipmi_intf * intf, int argc, char ** argv) lprintf(LOG_NOTICE, " 252: LED restore to local control"); lprintf(LOG_NOTICE, " 255: LED ON override"); - lprintf(LOG_NOTICE, - " <duration> 1 - 127: LED Lamp Test / on duration"); + lprintf(LOG_NOTICE, " <duration> 0 - 127: LED Lamp Test duration"); + lprintf(LOG_NOTICE, " 0 - 255: LED Lamp ON duration"); lprintf(LOG_NOTICE, " <color> 0: reserved"); lprintf(LOG_NOTICE, " 1: BLUE"); lprintf(LOG_NOTICE, " 2: RED"); @@ -2335,37 +2338,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..3900974 --- /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 < 4) { + 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/Makefile.in b/src/Makefile.in index 5da68bb..06b33a8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -291,6 +291,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/Makefile.in index daa57d1..f38697a 100644 --- a/src/plugins/Makefile.in +++ b/src/plugins/Makefile.in @@ -284,6 +284,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -380,8 +382,8 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ 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 libintf_la_LDFLAGS = -export-dynamic diff --git a/src/plugins/bmc/Makefile.in b/src/plugins/bmc/Makefile.in index 8c98861..6ed1ee7 100644 --- a/src/plugins/bmc/Makefile.in +++ b/src/plugins/bmc/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/dummy/Makefile.in b/src/plugins/dummy/Makefile.in index 1cd85a5..86475ba 100644 --- a/src/plugins/dummy/Makefile.in +++ b/src/plugins/dummy/Makefile.in @@ -211,6 +211,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/free/Makefile.in index 9b2eda0..d8eb9e6 100644 --- a/src/plugins/free/Makefile.in +++ b/src/plugins/free/Makefile.in @@ -215,6 +215,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/imb/Makefile.in index a65eca7..d1ded78 100644 --- a/src/plugins/imb/Makefile.in +++ b/src/plugins/imb/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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..19ba5e3 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,27 +347,26 @@ 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 */ + hints.ai_family = intf->ai_family; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 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/Makefile.in b/src/plugins/lan/Makefile.in index fc48fe4..9d1ce80 100644 --- a/src/plugins/lan/Makefile.in +++ b/src/plugins/lan/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/lanplus/Makefile.in index 09458aa..eef233d 100644 --- a/src/plugins/lanplus/Makefile.in +++ b/src/plugins/lanplus/Makefile.in @@ -242,6 +242,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c index 0bff5b2..8776212 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,29 @@ 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; } + + /* automatically detect interface request and response sizes */ + hpm2_detect_max_payload_size(intf); } - intf->manufacturer_id = ipmi_get_oem(intf); + bridgePossible = 1; - /* automatically detect interface request and response sizes */ - hpm2_detect_max_payload_size(intf); + if (!ipmi_oem_active(intf, "i82571spt")) { + intf->manufacturer_id = ipmi_get_oem(intf); + } 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 +3586,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 +3629,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 +3638,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 +3656,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/lipmi/Makefile.in b/src/plugins/lipmi/Makefile.in index d70d55d..eb8000f 100644 --- a/src/plugins/lipmi/Makefile.in +++ b/src/plugins/lipmi/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff --git a/src/plugins/open/Makefile.in b/src/plugins/open/Makefile.in index da116b7..bb4be5e 100644 --- a/src/plugins/open/Makefile.in +++ b/src/plugins/open/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/serial/Makefile.in index 9826ebf..cae1857 100644 --- a/src/plugins/serial/Makefile.in +++ b/src/plugins/serial/Makefile.in @@ -241,6 +241,8 @@ INTF_OPEN = @INTF_OPEN@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ 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/Makefile.in b/src/plugins/usb/Makefile.in new file mode 100644 index 0000000..298e11d --- /dev/null +++ b/src/plugins/usb/Makefile.in @@ -0,0 +1,637 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/plugins/usb +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libintf_usb_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la +am_libintf_usb_la_OBJECTS = usb.lo +libintf_usb_la_OBJECTS = $(am_libintf_usb_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libintf_usb_la_SOURCES) +DIST_SOURCES = $(libintf_usb_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ARCH = @ARCH@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASEDIR = @BASEDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTRO = @DISTRO@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTF_BMC = @INTF_BMC@ +INTF_BMC_LIB = @INTF_BMC_LIB@ +INTF_DUMMY = @INTF_DUMMY@ +INTF_DUMMY_LIB = @INTF_DUMMY_LIB@ +INTF_FREE = @INTF_FREE@ +INTF_FREE_LIB = @INTF_FREE_LIB@ +INTF_IMB = @INTF_IMB@ +INTF_IMB_LIB = @INTF_IMB_LIB@ +INTF_LAN = @INTF_LAN@ +INTF_LANPLUS = @INTF_LANPLUS@ +INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@ +INTF_LAN_LIB = @INTF_LAN_LIB@ +INTF_LIPMI = @INTF_LIPMI@ +INTF_LIPMI_LIB = @INTF_LIPMI_LIB@ +INTF_OPEN = @INTF_OPEN@ +INTF_OPEN_LIB = @INTF_OPEN_LIB@ +INTF_SERIAL = @INTF_SERIAL@ +INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ +IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OS = @OS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POW_LIB = @POW_LIB@ +PSTAMP = @PSTAMP@ +RANLIB = @RANLIB@ +RPMBUILD = @RPMBUILD@ +RPM_RELEASE = @RPM_RELEASE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_configure_args = @ac_configure_args@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +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 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/usb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/usb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libintf_usb.la: $(libintf_usb_la_OBJECTS) $(libintf_usb_la_DEPENDENCIES) $(EXTRA_libintf_usb_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libintf_usb_la_OBJECTS) $(libintf_usb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + + # + # 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. + # + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/plugins/usb/usb.c b/src/plugins/usb/usb.c new file mode 100644 index 0000000..0049400 --- /dev/null +++ b/src/plugins/usb/usb.c @@ -0,0 +1,614 @@ +/* + * 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) { + break; + } + + 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); + fp = NULL; + } + + 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[16]; + int numdev = 16; + 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; +} |