Compare commits

..

49 Commits

Author SHA1 Message Date
a6ff7b6cfb fru, sdr: Refactor description handling
Reduce code duplication, get rid of magic numbers, unused variables
and functions, and of unsafe memory handling in FRU and SDR description
printing.

Also add support for logging generic locator and fru locator SDR record
names during SDR population (`ipmitool sdr fill`).

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2020-05-26 23:16:51 +03:00
f80effb1fc sel: time: fix null pointer dereference in set
This is a refix of commit f0d5c17e
2020-02-12 16:37:02 +03:00
7ccea283dd fru, sdr: Fix id_string buffer overflows
Final part of the fixes for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

9 variants of stack buffer overflow when parsing `id_string` field of
SDR records returned from `CMD_GET_SDR` command.

SDR record structs have an `id_code` field, and an `id_string` `char`
array.

The length of `id_string` is calculated as `(id_code & 0x1f) + 1`,
which can be larger than expected 16 characters (if `id_code = 0xff`,
then length will be `(0xff & 0x1f) + 1 = 32`).

In numerous places, this can cause stack buffer overflow when copying
into fixed buffer of size `17` bytes from this calculated length.
2020-02-04 15:00:14 +03:00
d45572d71e lanp: Fix buffer overflows in get_lan_param_select
Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `get_lan_param_select` function is missing a validation check on the
response’s `data_len`, which it then returns to caller functions, where
stack buffer overflow can occur.
2020-02-04 14:59:55 +03:00
9452be8718 channel: Fix buffer overflow
Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `ipmi_get_channel_cipher_suites` function does not properly check
the final response’s `data_len`, which can lead to stack buffer overflow
on the final copy.
2020-02-04 14:59:52 +03:00
41d7026946 session: Fix buffer overflow in ipmi_get_session_info
Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `ipmi_get_session_info` function does not properly check the
response `data_len`, which is used as a copy size, allowing stack buffer
overflow.
2020-02-04 14:59:49 +03:00
840fb1cbb4 fru: Fix buffer overflow in ipmi_spd_print_fru
Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `ipmi_spd_print_fru` function has a similar issue as the one fixed
by the previous commit in `read_fru_area_section`. An initial request is
made to get the `fru.size`, which is used as the size for the allocation
of `spd_data`. Inside a loop, further requests are performed to get the
copy sizes which are not checked before being used as the size for a
copy into the buffer.
2020-02-04 14:59:43 +03:00
e824c23316 fru: Fix buffer overflow vulnerabilities
Partial fix for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

The `read_fru_area_section` function only performs size validation of
requested read size, and falsely assumes that the IPMI message will not
respond with more than the requested amount of data; it uses the
unvalidated response size to copy into `frubuf`. If the response is
larger than the request, this can result in overflowing the buffer.

The same issue affects the `read_fru_area` function.
2020-02-04 14:58:06 +03:00
7a66d8725d chassis: bootmbox: Refix 62a04390
Fix ipmitool not writing the last block of boot mailbox data if the
block is shorter than 3 bytes.

Signed-off-by: Ivan Mikhaylov <fr0st61te@gmail.com>
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2020-01-23 18:06:47 +03:00
63dd71c39c configure: Drop requirement for curses et. al libs
Libraries ncurses, curses, tinfo and termcap are not actually
needed as the tgetent() function listed as required is not actually
used anywhere in the code.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-12-05 13:45:57 +03:00
e60eac12cc configure: remove some duplicate code
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-12-05 13:45:57 +03:00
dec04e79fd doc: Update INSTALL to fix installation errors
The `sudo` was missing from `make install` which prevented installation
if build is performed, as it should be, by an unpriviliged user.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-29 14:34:20 +03:00
d9adbf12f1 ipmi_dcmi: fix typo in nm_policy_options initialization.
This re-enables "nm policy add" functionality.
2019-11-27 13:47:41 +03:00
5647cd16d2 Docs: Add info on packages to install on Ubuntu 16.04
Add some documenation on packages to install on Ubuntu 16.04 and
Fedora 31 before building the software.

This will make it easier for people who are building ipmitool as they
won't need to figure out all the package dependencies on their own.
2019-11-15 14:25:08 +03:00
42a023ff07 chassis: Refactor to get rid of strncmp()
For parameter checking replace calls to strncmp() with calls
to strcmp() in order to improve readability and get rid of literal
string lengths.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
58c9263a28 chassis: Refactor main for centralized exiting
In ipmi_chassis_main:

* Default to error return code (-1).

* Use centralized exit.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
0663814eec chassis: bootdev: Refactor more
* Get rid of magic '8' in bootdev options processing.

* Optimize the code of bootdev arguments processing, remove the
  special crafting of flags for 'clear-cmos' argument, make it use
  the same code as other options.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
aa72d9c426 chassis: bootdev: Refactor to reduce nesting
Move bootdev options parsing to a separate helper function

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
0854344db5 chassis: bootdev: Fix help message and its formatting
There was a wrong help message regarding the console redirection,
and also the help formatting was a bit off. Straightened this all up.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
4b89f1b42d chassis: bootparam/bootdev: Refactor for less magic
Refactor the boot flags decoder:

* Add macros for boot flag bits, replace magic numbers in
  the `chassis bootparam get 5` and in `chassis bootdev`
  handlers.

  The macros are prefixed with BFx_ where x stands for the
  boot flags data byte as per IPMI 2.0 specification Table 28-14;

* Add decoding of remote/redirected media boot flags;

* Remove erroneous decoding of boot flags byte 3 bit 1 as
  Sleep button lockout whereas the bit is a part of console
  redirection setting;

* Fix console redirection settings reported under the 'BIOS verbosity'
  header and vice versa;

* Fix resetting of all other boot flags in the data byte when
  setting any of the bits in the same byte. This fixes inability
  to set both 'efiboot' and 'persistent' bits at the same time,
  and other similar cases.

Resolves ipmitool/ipmitool#163
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-12 17:55:21 +03:00
0e3e436eb6 oem: supermicro: Add product codes from IPMICFG
ftp://ftp.supermicro.com/utility/IPMICFG/IPMICFG_1.30.0_build.190710.zip
contains MBType.dat file that lists all known Supermicro product IDs
with their respective names.

Import that knowledge into ipmitool.

Resolves ipmitool/ipmitool#151
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-11-06 18:50:08 +03:00
eed9d5950e lan: Refix 6e2b688e. Fix vlan range checking.
Commit 6e2b688e introduced a bug due to which VLAN id range checking
was negated and resulted in error messages printed for correct VLAN ids.

Resolves ipmitool/ipmitool#55

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-09-05 15:10:02 +03:00
4dc962b614 doc: Update man page regarding user set password
Document password length argument to "set password", as per usage info.

Since we don't check whether we're using IPMI1.5/2.0 when setting the
password, ipmitool can't reject 20-char passwords being sent to
16-char interfaces, so the behaviour is somewhat undefined.
For 20-chars, it's now clearer and long passwords will be rejected.

Man page changed to reflect the above.
2019-09-03 23:40:48 +03:00
6940a6717a user: Cleanup/refactor ipmi_user_password()
Get rid of magic numbers, fix some formatting, drop unneeded checks.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-09-03 23:40:48 +03:00
51a2ab8180 user: Improve password length handling
No longer truncate passwords (16 < p <= 20) silently, instead attempt
to set a 20-char password when such a password is given.
Fail if an explicit length is exceeded, and any time the upper limit
is exceeded.
2019-09-03 23:40:48 +03:00
af062a9a5e user: Alter "set password" usage information
This changes the usage string to match reality and note that [<16|20>]
is an optional argument to set password.
2019-09-03 23:40:48 +03:00
1724b031b3 intf: Add missing function declarations
ipmi_intf.h was missing a couple of declarations for the functions
used by fru, sdr and hpmfwupg modules. Add those declarations
to ipmi_intf.h and remove local declarations.

This fixes a couple of compilation warnings.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-08-29 12:26:40 +03:00
9006f2b26d doc: fix URL in README 2019-08-29 11:54:18 +03:00
b7db637984 event: Clean up event sending from a file
The ipmi_event_fromfile() function was massively repeating the code of
ipmi_send_platform_event() and ipmi_event_msg_print().

This commit cleans up ipmi_event_fromfile() to simply call
ipmi_send_platform_event() with all the prepared data read from the
file. That function in its turn calls ipmi_event_msg_print().

This commit also replaces the dummy generator ID 2 that was printed to
the user with a more relevant generator ID that will actually be sent
by ipmi_send_platform_event().

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-07-02 13:50:12 +03:00
82d6629a66 event: Clean up the event sending code
Get rid of magic numbers, reduce code duplication

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-07-02 13:50:12 +03:00
c396a310ba event: Fix event submission via SSIF
IPMI 2.0 specification is quite inconsistent about system interfaces.

They have section 1.7.16 "System Interfaces" that clearly states that
there are FOUR system interfaces (KCS, SMIC, BT and SSIF), but then they
have section 1.7.31 saying that "It is mandatory to implement a system
interface that is compatible with one of the **three** specified system
interfaces" without specifying which three of the four interfaces are
meant. Then in section 6 "IPMI Messaging interfaces" they again say that
"As mentioned earlier, there are three System Interface implementations
specified for the BMC: SMIC, KCS, and BT". Is all looks like during
update from 1.5 to 2.0 they have updated section 1.7.16, but forgot to
update Table 6-3, section 1.7.31 and section 6. Yet again, there is 'Get
System Interface Capabilities' command that has a parameter 'System
Interface Type' that can specify that SI is of SSIF type.

All that have lead to a situation where some BMC manufacturers treated
the specification as if it prohibited specifying media type 0xC
(which is "System Interface") for system interfaces using SSIF
(SMBus Sustem Interface), and so they specified an SMBUS media type
for their system interface channels.

As a result, ipmitool failed to properly send event data via such
system interfaces as it treated them as non-system and didn't add
the required Generator ID.

To mitigate the inconsistency of IPMI specification and yet not
ask BMC manufacturers to alter their code, thus increasing compatibility
with legacy BMCs, this commit adds checking of current interface number.
The system interface, according to Table 6-1 of IPMI Specification is
required to have channel number 15 (0Fh). So with this commit the
generator ID is added for any interfaces that are either marked
as media type 0Ch 'System Interface' or have channel number 0Fh.

Resolves ipmitool/ipmitool#111

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-07-02 13:50:12 +03:00
002e1d95f5 make: Use DESTDIR to install IANA PEN database
In order to support packaging, installation rules in Makefile
have to obey the specified DESTDIR. That support was missing
and is now added.

Signed-off-by: Andrey Kosteltsev <a.kosteltsev@yadro.com>
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-07-02 11:43:20 +03:00
2ee7aca4e4 lanplus: Fix embedded bridged responses handling
Resolves ipmitool/ipmitool#141

Signed-off-by: Dawid Frycki <dawid.frycki@intel.com>
2019-07-01 16:18:31 +03:00
efd28d1bc1 Update .gitignore
Ignore logs, ViM swap files, and patch rejects and originals.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-25 15:51:29 +03:00
d95775288d mc: Fix reporting of manufacturers > 64K
If a manufacturer's IANA PEN (aka manufacturer ID) was above
65535, it wasn't reported properly. Luckily there are no such
IDs so far, the biggest is 54077 as of 2019/06/18.

There is, however, an ID 0xFFFFFE used by fake_ipmistack
for debug purposes, and it was not reported correctly.

This commit expands the value argument to string searching functions
from 16-bit to 32-bit to allow for any possible IANA PEN.

Fixes: 73d6af5782
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-18 20:07:57 +03:00
ef78ef3792 Add installation of enterprise-numbers database
Download and install the IANA PEN database (enterprise-numbers).

The download is performed using either wget or curl,
and the database is installed into @IANADIR@.

Resolves ipmitool/ipmitool#11

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-18 16:43:41 +03:00
2676ae43fd Update documentation in regard to IANA PEN registry
Add information regarding IANA PEN registry locations into
ipmitool and ipmievd man pages. The locations in man pages are
automatically generated based on `configure` options.

Partially resolves ipmitool/ipmitool#11

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-18 16:43:41 +03:00
54abbaf0e8 Use configurable path to IANA PEN registry
Add support for IANADIR and IANAUSERDIR variables to configure
to allow for customizable locations of system and user-supplied
IANA PEN registry.

Also make path building code portable to Windows.

Partially resolves ipmitool/ipmitool#11

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-18 16:43:41 +03:00
bd0475ce4a Load IANA PEN registry from a file
Previously, the OEM names dictionary was compiled in and
updating it required rebuilding of `ipmitool`, thus taking a
long time for newly registered OEMs to get supported by the tool.

Building also required a direct internet connection to succeed.

With this commit, the OEM enterprise dictionary is now loaded from
either ${HOME}/.local/usr/share/misc/enterprise-numbers or from
/usr/share/misc/enterprise-numbers (in that precedence).

Those files can be downloaded from iana.org at
http://www.iana.org/assignments/enterprise-numbers

Partially resolves ipmitool/ipmitool#11

Fixes: 9d41136c9b
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-18 16:43:41 +03:00
b397a07e9e dbus: Replace obsolete INCLUDES with AM_CPPFLAGS
The `INCLUDES` variable is obsolete, `AM_CPPFLAGS` is the new name.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-13 12:24:07 +03:00
8071cf7389 oem: name change from Newisys to Viking Enterprise Solutions
Renamed the oem strings containing Newisys to Viking Enterprise Solutions.
IANA 9237
Built and tested with AMI's IPMI stack LTS 12.01.

Resolves ipmitool/ipmitool#124

Signed-off-by: dan mcgee <dan.mcgee@vikingenterprise.com>
Signed-off-by: dan mcgee <dan.mcgee@sanmina.com>
2019-06-11 17:58:29 +03:00
ca7767793e Fix default interface to behave as it did before
Prior to 95038ba01b the default interface
was 'open' for builds where it was available and 'lan' otherwise. Due to
a logic error in 95038ba01b, the default
interface was always getting set to lan unless it was specified by the
environment variable. This commit fixes the logic and sets the default
to open if it is available and lan otherwise.

Resolves ipmitool/ipmitool#128

Tested: ./configure # no options reports 'open' as default
        ./configure --enable-intf-open=no # reports lan as default
        ./configure --enable-intf-dbus DEFAULT_INTF=dbus # reports dbus

Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
2019-06-10 14:21:02 +03:00
a45704e5ea man: Add documentation for chassis bootmbox
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
94f7646a8e man: Update the chassis bootparam section
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
62a04390e1 chassis: Add boot initiator mailbox support
Add `chassis bootmbox` command to set and get Boot Initiator Mailbox
boot parameter (id 7) the easy way. The command allows for getting
and setting the data both in hex and text modes, as well as properly
decodes IANA Enterprise number for block 0. It can get/set the whole
mailbox at once or operate on separate data blocks.

This commit enhances the chassis_get_boot_param() function with extra
arguments to re-use its code in handling of the added command.

Documentation update will follow.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
de1d5c9924 chassis: Use command-specific completion code parser
Get/set system boot option commands have some command-specific
completion codes that are now reported as "Unknown (0080)", etc.

Use the previously introduced specific_val2str() to convert those
specific error codes to human-readable strings.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
73d6af5782 Add support for command-specific completion codes
Some commands may return command-specific completion codes.
Now they are all reported as 'Unknown'.
Add helper functions to support such command-specific codes.
Command handlers will need to define their own valstr arrays
with completion code descriptions and then use specific_val2str()
instead of generic val2str() to convert the completion code into
a string.

Also reduce code duplication in helper.c

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
c9510635d7 Add a helper htoipmi24() function
The function converts a host 32-bit integer into an IPMI
24-bit value (LSB first).

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
e11f463b4e Add a helper args2buf() function
The function converts a set of command line arguments representing
byte values into a byte buffer and verifies each individual value
to be a valid data byte.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-06-10 13:56:31 +03:00
35 changed files with 2028 additions and 558 deletions

7
.gitignore vendored
View File

@ -1,6 +1,10 @@
.deps
.dirstamp
.libs
.*.swp
*.log
*.rej
*.orig
*.o
*.lo
*.la
@ -29,6 +33,7 @@ control/prototype
control/rpmmacros
src/ipmievd
src/ipmitool
lib/ipmi_pen_list.inc.c
doc/ipmievd.8
doc/ipmitool.1
cscope.out
tags

View File

@ -22,12 +22,18 @@ project is tested automatically to build cleanly for the following
- Ubuntu 16.04 Xenial
- MacOS X 10.14 (Xcode 10.2)
For Ubuntu 16.04 it is recommended to do the following before building:
$ sudo apt install automake gcc git libreadline-dev libssl-dev libsystemd-dev libtool make wget
For Fedora 31 it is recommended to do the following before building:
$ sudo dnf install automake gcc git libtool make openssl-devel readline-devel systemd-devel wget
Basic Installation
==================
Briefly, the followong shell command should configure, build, and
install this package:
`./bootstrap && ./configure && make && make install`
`./bootstrap && ./configure && make && sudo make install`
The following more-detailed instructions are generic; see the
`README' file for instructions specific to this package. Some

View File

@ -41,11 +41,37 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure configure-stamp \
$(distdir).tar.gz $(distdir).tar.bz2
SUBDIRS = lib src include doc contrib control
IANA_PEN = http://www.iana.org/assignments/enterprise-numbers
dist-hook:
cp control/ipmitool.spec $(distdir)
install-data-local:
.PHONY: install-pen-database
if DOWNLOAD
enterprise-numbers:
@echo Downloading IANA PEN database...
@$(DOWNLOAD) "$(IANA_PEN)" > tmpfile.$$PPID || {\
echo "FAILED to download the IANA PEN database"; \
rm tmpfile.$$PPID; \
false; \
}
@mv tmpfile.$$PPID $@
install-pen-database: enterprise-numbers
mkdir -m 755 -p $(DESTDIR)$(IANADIR)
$(INSTALL_DATA) $< -t $(DESTDIR)$(IANADIR)/
else
install-pen-database:
@echo "*** NOT installing the IANA PEN database."
@echo "*** Don't know how to download it."
endif
install-data-local: install-pen-database
mkdir -p $(DESTDIR)$(DOCDIR)
$(INSTALL_DATA) $(DOCLIST) $(DESTDIR)$(DOCDIR)

2
README
View File

@ -399,7 +399,7 @@ IPMItool homepage
http://github.com/ipmitool/ipmitool
IPMItool manpage
https://github.com/ipmitool/ipmitool/blob/master/doc/ipmitool.1
https://github.com/ipmitool/ipmitool/blob/master/doc/ipmitool.1.in
Intelligent Platform Management Interface specification
https://www.intel.com/content/www/us/en/servers/ipmi/ipmi-home.html

View File

@ -4,6 +4,7 @@ dnl
m4_define([git_suffix], m4_esyscmd_s(./csv-revision))
AC_INIT([ipmitool], [1.8.18git_suffix])
AC_CONFIG_SRCDIR([src/ipmitool.c])
AC_CONFIG_COMMANDS_PRE([export prefix=$prefix])
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE([foreign])
AM_CONFIG_HEADER(config.h)
@ -17,6 +18,8 @@ AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_CHECK_PROG([RPMBUILD], [rpmbuild], [rpmbuild], [rpm])
AC_CHECK_PROG([SED], [sed], [sed])
AC_CHECK_PROG([WGET], [wget], [wget])
AC_CHECK_PROG([CURL], [curl], [curl])
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h string.h sys/ioctl.h sys/stat.h unistd.h paths.h])
@ -53,6 +56,23 @@ if test "x$exec_prefix" = "xNONE"; then
exec_prefix="$prefix"
fi
if test "x$WGET" = "x"; then
if test "x$CURL" = "x"; then
AC_MSG_WARN([** Neither wget nor curl could be found.])
AC_MSG_WARN([** IANA PEN database will not be installed by `make install` !])
else
DOWNLOAD="$CURL -#"
AM_CONDITIONAL([DOWNLOAD], [true])
fi
else
DOWNLOAD="$WGET -c -nd -O -"
AM_CONDITIONAL([DOWNLOAD], [true])
fi
AC_MSG_WARN([** Download is:])
AC_MSG_WARN($DOWNLOAD)
AC_SUBST(DOWNLOAD, $DOWNLOAD)
dnl
dnl set default option values
dnl
@ -596,30 +616,18 @@ fi
AC_SUBST(IPMITOOL_INTF_LIB)
if test "x$xenable_ipmishell" = "xyes"; then
AC_SEARCH_LIBS([tgetent], [tinfo ncurses curses readline termcap])
AC_SEARCH_LIBS([initscr], [ncurses curses], [have_curses=yes])
AC_SEARCH_LIBS([readline], [readline edit], [have_readline=yes])
if test "x$have_curses" != "xyes" || test "x$have_readline" != "xyes"; then
xenable_ipmishell=no
fi
fi
dnl check for readline library to enable ipmi shell
AC_ARG_ENABLE([ipmishell],
[AC_HELP_STRING([--enable-ipmishell],
[enable IPMI shell interface [default=auto]])],
[xenable_ipmishell=$enableval],
[])
dnl check for readline library to enable ipmi shell
if test "x$xenable_ipmishell" = "xyes"; then
AC_SEARCH_LIBS([tgetent], [tinfo ncurses curses readline termcap])
AC_SEARCH_LIBS([initscr], [ncurses curses], [have_curses=yes])
AC_SEARCH_LIBS([readline], [readline edit], [have_readline=yes])
if test "x$have_curses" != "xyes"; then
AC_MSG_ERROR([** Unable to find curses required by ipmishell.])
fi
if test "x$have_readline" != "xyes"; then
AC_MSG_ERROR([** Unable to find readline required by ipmishell.])
xenable_ipmishell=no
fi
AC_DEFINE(HAVE_READLINE, [1], [Define to 1 if readline present.])
fi
@ -672,13 +680,13 @@ AC_TRY_COMPILE([],[
)
dnl if no environment variable is set, set the default value for the default intf
if test "${xenable_intf_open}" = "xyes"; then
if test "${xenable_intf_open}" = "yes"; then
DEFAULT_INTF_NO_ENV=open
else dnl macOS does not build open interface, it defaults to lan
DEFAULT_INTF_NO_ENV=lan
fi
dnl allow for a default interface to be set on configure
AC_ARG_VAR(DEFAULT_INTF, [Set the default interface to use (default=${DEFAULT_INTF_NO_ENV})])
AC_ARG_VAR(DEFAULT_INTF, [Set the default interface to use (default='open' if available, 'lan' otherwise)])
dnl set the default value for the default interface environment variable
if test "x${DEFAULT_INTF}" == "x"; then
@ -691,6 +699,32 @@ if test "x${!xdefault_intf_is_enabled}" != "xyes"; then
AC_MSG_ERROR([** Cannot set ${DEFAULT_INTF} as default; ${DEFAULT_INTF} is not enabled. :${!xdefault_intf_is_enabled}:])
fi
AC_ARG_VAR(IANADIR, [Configure the path to IANA PEN dictionary (default=DATAROOTDIR/misc)])
AC_ARG_VAR(IANAUSERDIR, [Configure the path to IANA PEN dictionary wihtin the user's HOME directory (default=.local/usr/share/misc)])
if test "x${IANADIR}" == "x"; then
echo Set IANA PEN dictionary search path to ${datarootdir}/misc
IANADIR="${datarootdir}/misc"
fi
if test "x${IANAUSERDIR}" == "x"; then
IANAUSERDIR=".local/usr/share/misc"
echo Set user\'s IANA PEN dictionary search path to ${IANAUSERDIR}
fi
AH_TEMPLATE([IANADIR],[The path to system IANA PEN dictionary])
AC_DEFINE_UNQUOTED(IANADIR, "`eval "echo ${IANADIR}"`", [])
AH_TEMPLATE([IANAUSERDIR],[The subpath to user IANA PEN dictionary within the user's HOME])
AC_DEFINE_UNQUOTED(IANAUSERDIR, "`eval "echo ${IANAUSERDIR}"`", [])
AH_TEMPLATE([PATH_SEPARATOR], [The path separator string])
#if defined _WIN32 || defined __CYGWIN__
AC_DEFINE(PATH_SEPARATOR, "\\")
#else
AC_DEFINE(PATH_SEPARATOR, "/")
#endif
dnl Generate files for build
AC_CONFIG_FILES([Makefile
doc/Makefile
@ -717,6 +751,9 @@ AC_CONFIG_FILES([Makefile
src/plugins/serial/Makefile
src/plugins/dummy/Makefile])
AC_CONFIG_FILES([doc/ipmitool.1], [${SED} -i -e "s%\${prefix}%$prefix%" doc/ipmitool.1])
AC_CONFIG_FILES([doc/ipmievd.8], [${SED} -i -e "s%\${prefix}%$prefix%" doc/ipmievd.8])
AC_OUTPUT
AC_MSG_RESULT([])

View File

@ -217,6 +217,16 @@ Reading Sensors...
.br
Waiting for Events...
.br
.SH FILES
.TP
.B @IANADIR@/enterprise-numbers
system IANA PEN registry taken from http://www.iana.org/assignments/enterprise-numbers
.TP
.B ~/@IANAUSERDIR@/enterprise-numbers
user's override for the system IANA PEN registry, this file if it exists is loaded instead
of the system registry (see above).
.SH "AUTHOR"
Duncan Laurie <duncan@iceblink.org>
.SH "SEE ALSO"

View File

@ -259,11 +259,15 @@ system. It is thus recommended that IPMI password management only be done
over IPMIv2.0 \fIlanplus\fP interface or the system interface on the
local station.
For IPMI v1.5, the maximum password length is 16 characters.
Passwords longer than 16 characters will be truncated.
For IPMI v1.5, the maximum password length is 16 characters; longer
passwords might be truncated or rejected by the server, or rejected
by
.BR ipmitool .
For IPMI v2.0, the maximum password length is 20 characters; longer
passwords will be rejected by
.BR ipmitool .
For IPMI v2.0, the maximum password length is 20 characters;
longer passwords are truncated.
.SH "COMMANDS"
.TP
\fIhelp\fP
@ -3526,12 +3530,13 @@ Displays a list of user information for all defined userids.
Sets the username associated with the given userid.
.TP
\fIpassword\fP <\fBuserid\fR> [<\fBpassword\fR>]
\fIpassword\fP <\fBuserid\fR> [<\fBpassword\fR> [<\fB16|20\fR>]]
.br
Sets the password for the given userid. If no password is given,
the password is cleared (set to the NULL password). Be careful when
removing passwords from administrator\-level accounts.
removing passwords from administrator\-level accounts. If specified,
16 or 20 determines the maximum password length.
.RE
.TP
\fIdisable\fP <\fBuserid\fR>
@ -3818,6 +3823,15 @@ Chassis Power is on
.br
Chassis Power Control: Up/On
.SH FILES
.TP
.B @IANADIR@/enterprise-numbers
system IANA PEN registry taken from http://www.iana.org/assignments/enterprise-numbers
.TP
.B ~/@IANAUSERDIR@/enterprise-numbers
user's override for the system IANA PEN registry, this file if it exists is loaded instead
of the system registry (see above).
.SH "AUTHORS"
Originally written by Duncan Laurie <duncan@iceblink.org>.
.br

View File

@ -81,11 +81,11 @@ struct oemvalstr {
};
const char *
specific_val2str(uint16_t val,
specific_val2str(uint32_t val,
const struct valstr *specific,
const struct valstr *generic);
const char * val2str(uint16_t val, const struct valstr * vs);
const char * oemval2str(uint32_t oem,uint16_t val, const struct oemvalstr * vs);
const char *val2str(uint32_t val, const struct valstr * vs);
const char *oemval2str(uint32_t oem, uint32_t val, const struct oemvalstr * vs);
int str2double(const char * str, double * double_ptr);
int str2long(const char * str, int64_t * lng_ptr);
@ -106,7 +106,11 @@ 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);
uint32_t str2val32(const char *str, const struct valstr *vs);
static inline uint16_t str2val(const char *str, const struct valstr *vs)
{
return (uint16_t)str2val32(str, vs);
}
void print_valstr(const struct valstr * vs, const char * title, int loglevel);
void print_valstr_2col(const struct valstr * vs, const char * title, int loglevel);

View File

@ -283,7 +283,7 @@ typedef enum IPMI_OEM {
IPMI_OEM_MAGNUM = 5593,
IPMI_OEM_TYAN = 6653,
IPMI_OEM_QUANTA = 7244,
IPMI_OEM_NEWISYS = 9237,
IPMI_OEM_VIKING = 9237,
IPMI_OEM_ADVANTECH = 10297,
IPMI_OEM_FUJITSU_SIEMENS = 10368,
IPMI_OEM_AVOCENT = 10418,

View File

@ -57,6 +57,28 @@
#define IPMI_CHANNEL_SESSION_MULTI 0x80
#define IPMI_CHANNEL_SESSION_BASED 0xC0
/* Fixed channel numbers as per Table 6-1 */
typedef enum {
CH_PRIMARY_IPMB,
CH_IMP_SPECIFIC_1,
CH_IMP_SPECIFIC_2,
CH_IMP_SPECIFIC_3,
CH_IMP_SPECIFIC_4,
CH_IMP_SPECIFIC_5,
CH_IMP_SPECIFIC_6,
CH_IMP_SPECIFIC_7,
CH_IMP_SPECIFIC_8,
CH_IMP_SPECIFIC_9,
CH_IMP_SPECIFIC_A,
CH_IMP_SPECIFIC_B,
CH_RSVD1,
CH_RSVD2,
CH_CURRENT,
CH_SYSTEM,
CH_TOTAL,
CH_UNKNOWN = UINT8_MAX
} ipmi_channel_num_t;
/* (22.24) Get Channel Info */
struct channel_info_t {
uint8_t channel;
@ -189,7 +211,8 @@ int _ipmi_set_channel_access(struct ipmi_intf *intf,
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);
void ipmi_current_channel_info(struct ipmi_intf *intf,
struct channel_info_t *chinfo);
int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
uint8_t channel, uint8_t priv);

View File

@ -61,6 +61,33 @@ struct platform_event_msg {
#pragma pack(0)
#endif
/* See IPMI 2.0 Specification, Appendix G, Table G-1, "Event Commands" */
typedef enum {
IPMI_CMD_SET_EVENT_RCVR = 0,
IPMI_CMD_GET_EVENT_RCVR,
IPMI_CMD_PLATFORM_EVENT
} ipmi_event_cmd_t;
typedef enum {
PLATFORM_EVENT_DATA_LEN_NON_SI = sizeof(struct platform_event_msg),
PLATFORM_EVENT_DATA_LEN_SI, /* System interfaces require generator ID */
PLATFORM_EVENT_DATA_LEN_MAX = PLATFORM_EVENT_DATA_LEN_SI
} ipmi_platform_event_data_len_t;
/* See Table 5-4 */
typedef enum {
EVENT_SWID_BIOS_BASE = 0x00, /* BIOS */
EVENT_SWID_SMI_BASE = 0x10, /* SMI Handler */
EVENT_SWID_SMS_BASE = 0x20, /* System Management Software */
EVENT_SWID_OEM_BASE = 0x30, /* OEM */
EVENT_SWID_REMOTE_CONSOLE_BASE = 0x40, /* Remote Console SW */
EVENT_SWID_TERMINAL_MODE_BASE = 0x47 /* Terminal Mode RC SW */
} ipmi_event_swid_t;
#define EVENT_SWID(base, index) ((EVENT_SWID_##base##_BASE + index) & 0x7F)
/* See Figure 29-2, Table 32-1 */
#define EVENT_GENERATOR(base, index) (EVENT_SWID(base,index) << 1 | 1)
int ipmi_event_main(struct ipmi_intf *, int, char **);
#endif /*IPMI_EVENT_H*/

View File

@ -241,6 +241,9 @@ struct ipmi_intf {
void (*set_max_response_data_size)(struct ipmi_intf * intf, uint16_t size);
};
uint16_t ipmi_intf_get_max_request_data_size(struct ipmi_intf *intf);
uint16_t ipmi_intf_get_max_response_data_size(struct ipmi_intf *intf);
struct ipmi_intf * ipmi_intf_load(char * name);
void ipmi_intf_print(struct ipmi_intf_support * intflist);

View File

@ -104,6 +104,24 @@ enum {
#define GET_SENSOR_READING 0x2d
#define GET_SENSOR_TYPE 0x2f
/*
* IPMI Specification limits the length of the ID string to 16 bytes for
* SDR records, although the ID type/length code may contain a number up
* to 31 (0x1F). See IPMI 2.0 Specification Tables 43-6 through 43-8.
*/
#define SDR_TYPECODE_LEN_MASK 0x1f
#define SDR_ID_STRING_MAX 16
#define SDR_ID_STRLEN_BYTYPE(typelen) \
((size_t)__max(typelen & SDR_TYPECODE_LEN_MASK, SDR_ID_STRING_MAX))
#define SDR_ID_STRLEN(sdr) SDR_ID_STRLEN_BYTYPE((sdr)->id_code)
#define SDR_ID_TO_CSTRING(cstring, sdr) \
do { \
memset((cstring), 0, sizeof(cstring)); \
snprintf((cstring), sizeof(cstring), "%.*s", \
SDR_ID_STRLEN(sdr), (sdr)->id_string); \
} while(0)
#ifdef HAVE_PRAGMA_PACK
#pragma pack(1)
#endif
@ -466,7 +484,7 @@ struct sdr_record_compact_sensor {
uint8_t __reserved[3];
uint8_t oem; /* reserved for OEM use */
uint8_t id_code; /* sensor ID string type/length code */
uint8_t id_string[16]; /* sensor ID string bytes, only if id_code != 0 */
uint8_t id_string[SDR_ID_STRING_MAX]; /* sensor ID string bytes */
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
@ -517,7 +535,7 @@ struct sdr_record_eventonly_sensor {
uint8_t __reserved;
uint8_t oem; /* reserved for OEM use */
uint8_t id_code; /* sensor ID string type/length code */
uint8_t id_string[16]; /* sensor ID string bytes, only if id_code != 0 */
uint8_t id_string[SDR_ID_STRING_MAX]; /* sensor ID string bytes */
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
@ -587,7 +605,7 @@ struct sdr_record_full_sensor {
uint8_t __reserved[2];
uint8_t oem; /* reserved for OEM use */
uint8_t id_code; /* sensor ID string type/length code */
uint8_t id_string[16]; /* sensor ID string bytes, only if id_code != 0 */
uint8_t id_string[SDR_ID_STRING_MAX]; /* sensor ID string bytes */
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
@ -619,7 +637,7 @@ struct sdr_record_mc_locator {
struct entity_id entity;
uint8_t oem;
uint8_t id_code;
uint8_t id_string[16];
uint8_t id_string[SDR_ID_STRING_MAX];
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
@ -652,7 +670,7 @@ struct sdr_record_fru_locator {
struct entity_id entity;
uint8_t oem;
uint8_t id_code;
uint8_t id_string[16];
uint8_t id_string[SDR_ID_STRING_MAX];
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
@ -686,7 +704,7 @@ struct sdr_record_generic_locator {
struct entity_id entity;
uint8_t oem;
uint8_t id_code;
uint8_t id_string[16];
uint8_t id_string[SDR_ID_STRING_MAX];
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
@ -800,9 +818,12 @@ struct sdr_record_list {
#define SENSOR_TYPE_MAX 0x2C
struct sensor_reading {
char s_id[17]; /* name of the sensor */
char s_id[SDR_ID_STRING_MAX + 1]; /* sensor name, null-terminated */
union {
struct sdr_record_full_sensor *full;
struct sdr_record_compact_sensor *compact;
void *raw;
};
uint8_t s_reading_valid; /* read value valididity */
uint8_t s_scanning_disabled; /* read of value disabled */
uint8_t s_reading_unavailable; /* read value unavailable */
@ -848,7 +869,7 @@ uint8_t *ipmi_sdr_get_record(struct ipmi_intf *intf, struct sdr_get_rs *header,
void ipmi_sdr_end(struct ipmi_sdr_iterator *i);
int ipmi_sdr_print_sdr(struct ipmi_intf *intf, uint8_t type);
int ipmi_sdr_print_name_from_rawentry(uint16_t id, uint8_t type,uint8_t * raw);
int sdr_get_name_from_rawentry(uint8_t type, void *raw, char *buf, size_t len);
int ipmi_sdr_print_rawentry(struct ipmi_intf *intf, uint8_t type, uint8_t * raw,
int len);
int ipmi_sdr_print_listentry(struct ipmi_intf *intf,

View File

@ -679,7 +679,7 @@ void ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_e
void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc);
const char * ipmi_get_sensor_type(struct ipmi_intf *intf, uint8_t code);
uint16_t ipmi_sel_get_std_entry(struct ipmi_intf * intf, uint16_t id, struct sel_event_record * evt);
char * get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
char * get_viking_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
IPMI_OEM ipmi_get_oem(struct ipmi_intf * intf);
char * ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
int ipmi_sel_oem_init(const char * filename);

View File

@ -53,8 +53,10 @@ extern const struct valstr ipmi_chassis_power_control_vals[];
extern const struct valstr ipmi_auth_algorithms[];
extern const struct valstr ipmi_integrity_algorithms[];
extern const struct valstr ipmi_encryption_algorithms[];
extern const struct valstr ipmi_oem_info[];
extern const struct valstr ipmi_user_enable_status_vals[];
extern const struct valstr *ipmi_oem_info;
int ipmi_oem_info_init();
void ipmi_oem_info_free();
extern const struct valstr picmg_frucontrol_vals[];
extern const struct valstr picmg_clk_family_vals[];

View File

@ -31,7 +31,6 @@
AUTOMAKE_OPTIONS = subdir-objects
AM_CPPFLAGS = -I$(top_srcdir)/include
MAINTAINERCLEANFILES = Makefile.in
PEN_LIST = $(srcdir)/ipmi_pen_list.inc.c
noinst_LTLIBRARIES = libipmitool.la
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
@ -49,8 +48,3 @@ libipmitool_la_LDFLAGS = -export-dynamic
libipmitool_la_LIBADD = -lm
libipmitool_la_DEPENDENCIES =
$(PEN_LIST):
$(srcdir)/create_pen_list $(PEN_LIST)
ipmi_strings.lo: $(PEN_LIST)

View File

@ -1,77 +0,0 @@
#!/bin/bash
# vi: set ts=2 sw=2 et :
#
# IANA PEN List generator
#
# This script takes the official IANA PEN registry and generates
# a C language output for inclusion into ipmi_strings.c
#
# Copyright (c) 2018 Alexander Amelkin <alexander@amelkin.msk.ru>
#
# 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.
#
OUTFILE=$1
PENLIST_URL=https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
if [ -z "$OUTFILE" ]; then
echo $0: Must specify output file
exit
fi
parse_pen_list() {
iconv -f utf8 -t ascii//TRANSLIT//IGNORE \
| awk '
/^[0-9]+/ {
if(PEN) {
print "{ " PEN ", \"" ENTERPRISE "\" },"
}
PEN=$1
}
/^ [[:alnum:]]/ {
# Remove leading spaces
sub(/^[[:space:]]+/,"")
# Remove question marks (Chinese characters after iconv)
gsub(/\?/,"");
# Remove non-printable characters
gsub(/[^[:print:]]/,"");
# Escape slashes and double quotes
gsub(/["\\]/,"\\\\&")
ENTERPRISE=$0;
}
END {
if(PEN) {
print "{ " PEN ", \"" ENTERPRISE "\" },"
}
}'
}
echo "Generating IANA PEN list..."
curl -# "$PENLIST_URL" | parse_pen_list > "$OUTFILE"

View File

@ -1621,7 +1621,7 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
struct ipmi_rq req;
struct fru_info fru;
uint8_t *spd_data, msg_data[4];
int len, offset;
uint32_t len, offset;
msg_data[0] = id;
@ -1697,6 +1697,13 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
}
len = rsp->data[0];
if(rsp->data_len < 1
|| len > rsp->data_len - 1
|| len > fru.size - offset)
{
printf(" Not enough buffer size");
return -1;
}
memcpy(&spd_data[offset], rsp->data + 1, len);
offset += len;
} while (offset < fru.size);

View File

@ -329,7 +329,7 @@ mac2str(const uint8_t *buf)
*/
static
inline
off_t find_val_idx(uint16_t val, const struct valstr *vs)
off_t find_val_idx(uint32_t val, const struct valstr *vs)
{
if (vs) {
for (off_t i = 0; vs[i].str; ++i) {
@ -351,7 +351,7 @@ off_t find_val_idx(uint16_t val, const struct valstr *vs)
*/
static
inline
const char *unknown_val_str(uint16_t val)
const char *unknown_val_str(uint32_t val)
{
static char un_str[32];
memset(un_str, 0, 32);
@ -361,7 +361,7 @@ const char *unknown_val_str(uint16_t val)
}
const char *
specific_val2str(uint16_t val,
specific_val2str(uint32_t val,
const struct valstr *specific,
const struct valstr *generic)
{
@ -378,13 +378,13 @@ specific_val2str(uint16_t val,
return unknown_val_str(val);
}
const char * val2str(uint16_t val, const struct valstr *vs)
const char *val2str(uint32_t val, const struct valstr *vs)
{
return specific_val2str(val, NULL, vs);
}
const char * oemval2str(uint32_t oem, uint16_t val,
const char *oemval2str(uint32_t oem, uint32_t val,
const struct oemvalstr *vs)
{
int i;
@ -642,7 +642,7 @@ int str2uchar(const char * str, uint8_t * uchr_ptr)
return 0;
} /* str2uchar(...) */
uint16_t str2val(const char *str, const struct valstr *vs)
uint32_t str2val32(const char *str, const struct valstr *vs)
{
int i;

View File

@ -244,10 +244,28 @@ ipmi_1_5_authtypes(uint8_t n)
return supportedTypes;
}
uint8_t
ipmi_current_channel_medium(struct ipmi_intf *intf)
void
ipmi_current_channel_info(struct ipmi_intf *intf,
struct channel_info_t *chinfo)
{
return ipmi_get_channel_medium(intf, 0xE);
int ccode = 0;
chinfo->channel = CH_CURRENT;
ccode = _ipmi_get_channel_info(intf, chinfo);
if (ccode) {
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
if (ccode > 0) {
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
val2str(ccode, completion_code_vals));
}
else {
eval_ccode(ccode);
}
}
chinfo->channel = CH_UNKNOWN;
chinfo->medium = IPMI_CHANNEL_MEDIUM_RESERVED;
}
return;
}
/**
@ -480,7 +498,10 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf,
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
if (rsp->ccode || rsp->data_len < 1) {
if (rsp->ccode
|| rsp->data_len < 1
|| rsp->data_len > sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)
{
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
@ -684,13 +705,16 @@ ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel)
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) {
if (ccode) {
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
if (ccode > 0) {
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
val2str(ccode, completion_code_vals));
}
else {
eval_ccode(ccode);
}
}
return IPMI_CHANNEL_MEDIUM_RESERVED;
}
lprintf(LOG_DEBUG, "Channel type: %s",

View File

@ -53,6 +53,96 @@
#define CHASSIS_BOOT_MBOX_MAX_BLOCK 0xFF
#define CHASSIS_BOOT_MBOX_MAX_BLOCKS (CHASSIS_BOOT_MBOX_MAX_BLOCK + 1)
/* Get/Set system boot option boot flags bit definitions */
/* Boot flags byte 1 bits */
#define BF1_VALID_SHIFT 7
#define BF1_INVALID 0
#define BF1_VALID (1 << BF1_VALID_SHIFT)
#define BF1_VALID_MASK BF1_VALID
#define BF1_PERSIST_SHIFT 6
#define BF1_ONCE 0
#define BF1_PERSIST (1 << BF1_PERSIST_SHIFT)
#define BF1_PERSIST_MASK BF1_PERSIST
#define BF1_BOOT_TYPE_SHIFT 5
#define BF1_BOOT_TYPE_LEGACY 0
#define BF1_BOOT_TYPE_EFI (1 << BF1_BOOT_TYPE_SHIFT)
#define BF1_BOOT_TYPE_MASK BF1_BOOT_TYPE_EFI
/* Boot flags byte 2 bits */
#define BF2_CMOS_CLEAR_SHIFT 7
#define BF2_CMOS_CLEAR (1 << BF2_CMOS_CLEAR_SHIFT)
#define BF2_CMOS_CLEAR_MASK BF2_CMOS_CLEAR
#define BF2_KEYLOCK_SHIFT 6
#define BF2_KEYLOCK (1 << BF2_KEYLOCK_SHIFT)
#define BF2_KEYLOCK_MASK BF2_KEYLOCK
#define BF2_BOOTDEV_SHIFT 2
#define BF2_BOOTDEV_DEFAULT (0 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_PXE (1 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_HDD (2 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_HDD_SAFE (3 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_DIAG_PART (4 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_CDROM (5 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_SETUP (6 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_REMOTE_FDD (7 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_REMOTE_CDROM (8 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_REMOTE_PRIMARY_MEDIA (9 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_REMOTE_HDD (11 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_FDD (15 << BF2_BOOTDEV_SHIFT)
#define BF2_BOOTDEV_MASK (0xF << BF2_BOOTDEV_SHIFT)
#define BF2_BLANK_SCREEN_SHIFT 1
#define BF2_BLANK_SCREEN (1 << BF2_BLANK_SCREEN_SHIFT)
#define BF2_BLANK_SCREEN_MASK BF2_BLANK_SCREEN
#define BF2_RESET_LOCKOUT_SHIFT 0
#define BF2_RESET_LOCKOUT (1 << BF2_RESET_LOCKOUT_SHIFT)
#define BF2_RESET_LOCKOUT_MASK BF2_RESET_LOCKOUT
/* Boot flags byte 3 bits */
#define BF3_POWER_LOCKOUT_SHIFT 7
#define BF3_POWER_LOCKOUT (1 << BF3_POWER_LOCKOUT_SHIFT)
#define BF3_POWER_LOCKOUT_MASK BF3_POWER_LOCKOUT
#define BF3_VERBOSITY_SHIFT 5
#define BF3_VERBOSITY_DEFAULT (0 << BF3_VERBOSITY_SHIFT)
#define BF3_VERBOSITY_QUIET (1 << BF3_VERBOSITY_SHIFT)
#define BF3_VERBOSITY_VERBOSE (2 << BF3_VERBOSITY_SHIFT)
#define BF3_VERBOSITY_MASK (3 << BF3_VERBOSITY_SHIFT)
#define BF3_EVENT_TRAPS_SHIFT 4
#define BF3_EVENT_TRAPS (1 << BF3_EVENT_TRAPS_SHIFT)
#define BF3_EVENT_TRAPS_MASK BF3_EVENT_TRAPS
#define BF3_PASSWD_BYPASS_SHIFT 3
#define BF3_PASSWD_BYPASS (1 << BF3_PASSWD_BYPASS_SHIFT)
#define BF3_PASSWD_BYPASS_MASK BF3_PASSWD_BYPASS
#define BF3_SLEEP_LOCKOUT_SHIFT 2
#define BF3_SLEEP_LOCKOUT (1 << BF3_SLEEP_LOCKOUT_SHIFT)
#define BF3_SLEEP_LOCKOUT_MASK BF3_SLEEP_LOCKOUT
#define BF3_CONSOLE_REDIR_SHIFT 0
#define BF3_CONSOLE_REDIR_DEFAULT (0 << BF3_CONSOLE_REDIR_SHIFT)
#define BF3_CONSOLE_REDIR_SUPPRESS (1 << BF3_CONSOLE_REDIR_SHIFT)
#define BF3_CONSOLE_REDIR_ENABLE (2 << BF3_CONSOLE_REDIR_SHIFT)
#define BF3_CONSOLE_REDIR_MASK (3 << BF3_CONSOLE_REDIR_SHIFT)
/* Boot flags byte 4 bits */
#define BF4_SHARED_MODE_SHIFT 3
#define BF4_SHARED_MODE (1 << BF4_SHARED_MODE_SHIFT)
#define BF4_SHARED_MODE_MASK BF4_SHARED_MODE
#define BF4_BIOS_MUX_SHIFT 0
#define BF4_BIOS_MUX_DEFAULT (0 << BF4_BIOS_MUX_SHIFT)
#define BF4_BIOS_MUX_BMC (1 << BF4_BIOS_MUX_SHIFT)
#define BF4_BIOS_MUX_SYSTEM (2 << BF4_BIOS_MUX_SHIFT)
#define BF4_BIOS_MUX_MASK (7 << BF4_BIOS_MUX_SHIFT)
typedef struct {
uint8_t iana[CHASSIS_BOOT_MBOX_IANA_SZ];
uint8_t data[CHASSIS_BOOT_MBOX_BLOCK0_SZ];
@ -165,7 +255,7 @@ ipmi_chassis_identify(struct ipmi_intf * intf, char * arg)
req.msg.cmd = 0x4;
if (arg) {
if (strncmp(arg, "force", 5) == 0) {
if (!strcmp(arg, "force")) {
identify_data.force_on = 1;
} else {
if ( (rc = str2uchar(arg, &identify_data.interval)) != 0) {
@ -776,79 +866,147 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
{
printf( " Boot Flags :\n");
if((rsp->data[2]&0x80) == 0x80)
if(rsp->data[2] & BF1_VALID)
printf(" - Boot Flag Valid\n");
else
printf(" - Boot Flag Invalid\n");
if((rsp->data[2]&0x40) == 0x40)
if(rsp->data[2] & BF1_PERSIST)
printf(" - Options apply to all future boots\n");
else
printf(" - Options apply to only next boot\n");
if((rsp->data[2]&0x20) == 0x20)
if(rsp->data[2] & BF1_BOOT_TYPE_EFI)
printf(" - BIOS EFI boot \n");
else
printf(" - BIOS PC Compatible (legacy) boot \n");
if((rsp->data[3]&0x80) == 0x80)
if(rsp->data[3] & BF2_CMOS_CLEAR)
printf(" - CMOS Clear\n");
if((rsp->data[3]&0x40) == 0x40)
if(rsp->data[3] & BF2_KEYLOCK)
printf(" - Lock Keyboard\n");
printf(" - Boot Device Selector : ");
switch( ((rsp->data[3]>>2)&0x0f))
switch(rsp->data[3] & BF2_BOOTDEV_MASK)
{
case 0: printf("No override\n"); break;
case 1: printf("Force PXE\n"); break;
case 2: printf("Force Boot from default Hard-Drive\n"); break;
case 3: printf("Force Boot from default Hard-Drive, request Safe-Mode\n"); break;
case 4: printf("Force Boot from Diagnostic Partition\n"); break;
case 5: printf("Force Boot from CD/DVD\n"); break;
case 6: printf("Force Boot into BIOS Setup\n"); break;
case 15: printf("Force Boot from Floppy/primary removable media\n"); break;
default: printf("Flag error\n"); break;
case BF2_BOOTDEV_DEFAULT:
printf("No override\n");
break;
case BF2_BOOTDEV_PXE:
printf("Force PXE\n");
break;
case BF2_BOOTDEV_HDD:
printf("Force Boot from default Hard-Drive\n");
break;
case BF2_BOOTDEV_HDD_SAFE:
printf("Force Boot from default Hard-Drive, "
"request Safe-Mode\n");
break;
case BF2_BOOTDEV_DIAG_PART:
printf("Force Boot from Diagnostic Partition\n");
break;
case BF2_BOOTDEV_CDROM:
printf("Force Boot from CD/DVD\n");
break;
case BF2_BOOTDEV_SETUP:
printf("Force Boot into BIOS Setup\n");
break;
case BF2_BOOTDEV_REMOTE_FDD:
printf("Force Boot from remotely connected "
"Floppy/primary removable media\n");
break;
case BF2_BOOTDEV_REMOTE_CDROM:
printf("Force Boot from remotely connected "
"CD/DVD\n");
break;
case BF2_BOOTDEV_REMOTE_PRIMARY_MEDIA:
printf("Force Boot from primary remote media\n");
break;
case BF2_BOOTDEV_REMOTE_HDD:
printf("Force Boot from remotely connected "
"Hard-Drive\n");
break;
case BF2_BOOTDEV_FDD:
printf("Force Boot from Floppy/primary "
"removable media\n");
break;
default:
printf("Flag error\n");
break;
}
if((rsp->data[3]&0x02) == 0x02)
if(rsp->data[3] & BF2_BLANK_SCREEN)
printf(" - Screen blank\n");
if((rsp->data[3]&0x01) == 0x01)
if(rsp->data[3] & BF2_RESET_LOCKOUT)
printf(" - Lock out Reset buttons\n");
if((rsp->data[4]&0x80) == 0x80)
printf(" - Lock out (power off/sleep request) vi Power Button\n");
printf(" - Console Redirection control : ");
switch( ((rsp->data[4]>>5)&0x03))
{
case 0: printf("System Default\n"); break;
case 1: printf("Request Quiet Display\n"); break;
case 2: printf("Request Verbose Display\n"); break;
default: printf("Flag error\n"); break;
}
if((rsp->data[4]&0x10) == 0x10)
printf(" - Force progress event traps\n");
if((rsp->data[4]&0x08) == 0x08)
printf(" - User password bypass\n");
if((rsp->data[4]&0x04) == 0x04)
printf(" - Lock Out Sleep Button\n");
if((rsp->data[4]&0x02) == 0x02)
printf(" - Lock Out Sleep Button\n");
if(rsp->data[4] & BF3_POWER_LOCKOUT)
printf(" - Lock out (power off/sleep "
"request) via Power Button\n");
printf(" - BIOS verbosity : ");
switch( ((rsp->data[4]>>0)&0x03))
switch(rsp->data[4] & BF3_VERBOSITY_MASK)
{
case 0: printf("Console redirection occurs per BIOS configuration setting (default)\n"); break;
case 1: printf("Suppress (skip) console redirection if enabled\n"); break;
case 2: printf("Request console redirection be enabled\n"); break;
default: printf("Flag error\n"); break;
case BF3_VERBOSITY_DEFAULT:
printf("System Default\n");
break;
case BF3_VERBOSITY_QUIET:
printf("Request Quiet Display\n");
break;
case BF3_VERBOSITY_VERBOSE:
printf("Request Verbose Display\n");
break;
default:
printf("Flag error\n");
break;
}
if(rsp->data[4] & BF3_EVENT_TRAPS)
printf(" - Force progress event traps\n");
if(rsp->data[4] & BF3_PASSWD_BYPASS)
printf(" - User password bypass\n");
if(rsp->data[4] & BF3_SLEEP_LOCKOUT)
printf(" - Lock Out Sleep Button\n");
printf(" - Console Redirection control : ");
switch(rsp->data[4] & BF3_CONSOLE_REDIR_MASK)
{
case BF3_CONSOLE_REDIR_DEFAULT:
printf(
"Console redirection occurs per BIOS "
"configuration setting (default)\n");
break;
case BF3_CONSOLE_REDIR_SUPPRESS:
printf("Suppress (skip) console redirection "
"if enabled\n");
break;
case BF3_CONSOLE_REDIR_ENABLE:
printf("Request console redirection be "
"enabled\n");
break;
default:
printf("Flag error\n");
break;
}
if((rsp->data[5]&0x08) == 0x08)
if(rsp->data[5] & BF4_SHARED_MODE)
printf(" - BIOS Shared Mode Override\n");
printf(" - BIOS Mux Control Override : ");
switch( ((rsp->data[5]>>0)&0x07))
{
case 0: printf("BIOS uses recommended setting of the mux at the end of POST\n"); break;
case 1: printf("Requests BIOS to force mux to BMC at conclusion of POST/start of OS boot\n"); break;
case 2: printf("Requests BIOS to force mux to system at conclusion of POST/start of OS boot\n"); break;
default: printf("Flag error\n"); break;
switch (rsp->data[5] & BF4_BIOS_MUX_MASK) {
case BF4_BIOS_MUX_DEFAULT:
printf("BIOS uses recommended setting of the "
"mux at the end of POST\n");
break;
case BF4_BIOS_MUX_BMC:
printf(
"Requests BIOS to force mux to BMC at "
"conclusion of POST/start of OS boot\n");
break;
case BF4_BIOS_MUX_SYSTEM:
printf(
"Requests BIOS to force mux to system "
"at conclusion of POST/start of "
"OS boot\n");
break;
default:
printf("Flag error\n");
break;
}
}
break;
@ -1115,29 +1273,43 @@ ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
if (!arg)
flags[1] |= 0x00;
else if (strncmp(arg, "none", 4) == 0)
else if (!strcmp(arg, "none"))
flags[1] |= 0x00;
else if (strncmp(arg, "pxe", 3) == 0 ||
strncmp(arg, "force_pxe", 9) == 0)
else if (!strcmp(arg, "pxe") ||
!strcmp(arg, "force_pxe"))
{
flags[1] |= 0x04;
else if (strncmp(arg, "disk", 4) == 0 ||
strncmp(arg, "force_disk", 10) == 0)
}
else if (!strcmp(arg, "disk") ||
!strcmp(arg, "force_disk"))
{
flags[1] |= 0x08;
else if (strncmp(arg, "safe", 4) == 0 ||
strncmp(arg, "force_safe", 10) == 0)
}
else if (!strcmp(arg, "safe") ||
!strcmp(arg, "force_safe"))
{
flags[1] |= 0x0c;
else if (strncmp(arg, "diag", 4) == 0 ||
strncmp(arg, "force_diag", 10) == 0)
}
else if (!strcmp(arg, "diag") ||
!strcmp(arg, "force_diag"))
{
flags[1] |= 0x10;
else if (strncmp(arg, "cdrom", 5) == 0 ||
strncmp(arg, "force_cdrom", 11) == 0)
}
else if (!strcmp(arg, "cdrom") ||
!strcmp(arg, "force_cdrom"))
{
flags[1] |= 0x14;
else if (strncmp(arg, "floppy", 6) == 0 ||
strncmp(arg, "force_floppy", 12) == 0)
}
else if (!strcmp(arg, "floppy") ||
!strcmp(arg, "force_floppy"))
{
flags[1] |= 0x3c;
else if (strncmp(arg, "bios", 4) == 0 ||
strncmp(arg, "force_bios", 10) == 0)
}
else if (!strcmp(arg, "bios") ||
!strcmp(arg, "force_bios"))
{
flags[1] |= 0x18;
}
else {
lprintf(LOG_ERR, "Invalid argument: %s", arg);
rc = -1;
@ -1236,7 +1408,8 @@ chassis_set_bootmailbox(struct ipmi_intf *intf, int16_t block, bool use_text,
* We need to write all data, so calculate the data
* size in blocks and set the starting block to zero.
*/
blocks = datasize;
blocks = CHASSIS_BOOT_MBOX_IANA_SZ;
blocks += datasize;
blocks += CHASSIS_BOOT_MBOX_BLOCK_SZ - 1;
blocks /= CHASSIS_BOOT_MBOX_BLOCK_SZ;
@ -1508,25 +1681,25 @@ ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv)
int rc = 0;
uint8_t ctl = 0;
if ((argc < 1) || (strncmp(argv[0], "help", 4) == 0)) {
if (argc < 1 || !strcmp(argv[0], "help")) {
lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
return 0;
}
if (strncmp(argv[0], "status", 6) == 0) {
if (!strcmp(argv[0], "status")) {
rc = ipmi_chassis_print_power_status(intf);
return rc;
}
if ((strncmp(argv[0], "up", 2) == 0) || (strncmp(argv[0], "on", 2) == 0))
if (!strcmp(argv[0], "up") || !strcmp(argv[0], "on"))
ctl = IPMI_CHASSIS_CTL_POWER_UP;
else if ((strncmp(argv[0], "down", 4) == 0) || (strncmp(argv[0], "off", 3) == 0))
else if (!strcmp(argv[0], "down") || !strcmp(argv[0], "off"))
ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
else if (strncmp(argv[0], "cycle", 5) == 0)
else if (!strcmp(argv[0], "cycle"))
ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
else if (strncmp(argv[0], "reset", 5) == 0)
else if (!strcmp(argv[0], "reset"))
ctl = IPMI_CHASSIS_CTL_HARD_RESET;
else if (strncmp(argv[0], "diag", 4) == 0)
else if (!strcmp(argv[0], "diag"))
ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
else if ((strncmp(argv[0], "acpi", 4) == 0) || (strncmp(argv[0], "soft", 4) == 0))
else if (!strcmp(argv[0], "acpi") || !strcmp(argv[0], "soft"))
ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
else {
lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[0]);
@ -1554,58 +1727,270 @@ ipmi_chassis_set_bootflag_help()
get_bootparam_options("options=help", &set_flag, &clr_flag);
}
/*
* Sugar. Macros for internal use by bootdev_parse_options() to make
* the structure initialization look better. Can't use scope-limited
* static consts for initializers with gcc5, alas.
*/
#define BF1_OFFSET 0
#define BF2_OFFSET 1
#define BF3_OFFSET 2
#define BF4_OFFSET 3
#define BF_BYTE_COUNT 5
/* A helper for ipmi_chassis_main() to parse bootdev options */
static
bool
bootdev_parse_options(char *optstring, uint8_t flags[])
{
char *token;
char *saveptr = NULL;
int optionError = 0;
static const struct bootdev_opt_s {
char *name;
off_t offset;
unsigned char mask;
unsigned char value;
char *desc;
} *op;
static const struct bootdev_opt_s options[] = {
/* data 1 */
{
"valid",
BF1_OFFSET,
BF1_VALID_MASK,
BF1_VALID,
"Boot flags valid"
},
{
"persistent",
BF1_OFFSET,
BF1_PERSIST_MASK,
BF1_PERSIST,
"Changes are persistent for "
"all future boots"
},
{
"efiboot",
BF1_OFFSET,
BF1_BOOT_TYPE_MASK,
BF1_BOOT_TYPE_EFI,
"Extensible Firmware Interface "
"Boot (EFI)"
},
/* data 2 */
{
"clear-cmos",
BF2_OFFSET,
BF2_CMOS_CLEAR_MASK,
BF2_CMOS_CLEAR,
"CMOS clear"
},
{
"lockkbd",
BF2_OFFSET,
BF2_KEYLOCK_MASK,
BF2_KEYLOCK,
"Lock Keyboard"
},
/* data2[5:2] is parsed elsewhere */
{
"screenblank",
BF2_OFFSET,
BF2_BLANK_SCREEN_MASK,
BF2_BLANK_SCREEN,
"Screen Blank"
},
{
"lockoutreset",
BF2_OFFSET,
BF2_RESET_LOCKOUT_MASK,
BF2_RESET_LOCKOUT,
"Lock out Reset buttons"
},
/* data 3 */
{
"lockout_power",
BF3_OFFSET,
BF3_POWER_LOCKOUT_MASK,
BF3_POWER_LOCKOUT,
"Lock out (power off/sleep "
"request) via Power Button"
},
{
"verbose=default",
BF3_OFFSET,
BF3_VERBOSITY_MASK,
BF3_VERBOSITY_DEFAULT,
"Request quiet BIOS display"
},
{
"verbose=no",
BF3_OFFSET,
BF3_VERBOSITY_MASK,
BF3_VERBOSITY_QUIET,
"Request quiet BIOS display"
},
{
"verbose=yes",
BF3_OFFSET,
BF3_VERBOSITY_MASK,
BF3_VERBOSITY_VERBOSE,
"Request verbose BIOS display"
},
{
"force_pet",
BF3_OFFSET,
BF3_EVENT_TRAPS_MASK,
BF3_EVENT_TRAPS,
"Force progress event traps"
},
{
"upw_bypass",
BF3_OFFSET,
BF3_PASSWD_BYPASS_MASK,
BF3_PASSWD_BYPASS,
"User password bypass"
},
{
"lockout_sleep",
BF3_OFFSET,
BF3_SLEEP_LOCKOUT_MASK,
BF3_SLEEP_LOCKOUT,
"Lock out the Sleep button"
},
{
"cons_redirect=default",
BF3_OFFSET,
BF3_CONSOLE_REDIR_MASK,
BF3_CONSOLE_REDIR_DEFAULT,
"Console redirection occurs per "
"BIOS configuration setting"
},
{
"cons_redirect=skip",
BF3_OFFSET,
BF3_CONSOLE_REDIR_MASK,
BF3_CONSOLE_REDIR_SUPPRESS,
"Suppress (skip) console "
"redirection if enabled"
},
{
"cons_redirect=enable",
BF3_OFFSET,
BF3_CONSOLE_REDIR_MASK,
BF3_CONSOLE_REDIR_ENABLE,
"Request console redirection "
"be enabled"
},
/* data 4 */
/* data4[7:4] reserved */
/* data4[3] BIOS Shared Mode Override, not implemented here */
/* data4[2:0] BIOS Mux Control Override, not implemented here */
/* data5 reserved */
{NULL} /* End marker */
};
memset(&flags[0], 0, BF_BYTE_COUNT);
token = strtok_r(optstring, ",", &saveptr);
while (token) {
if (strcmp(token, "help") == 0) {
optionError = 1;
break;
}
for (op = options; op->name; ++op) {
if (strcmp(token, op->name) == 0) {
flags[op->offset] &= ~(op->mask);
flags[op->offset] |= op->value;
break;
}
}
if (!op->name) {
/* Option not found */
optionError = 1;
lprintf(LOG_ERR, "Invalid option: %s", token);
}
token = strtok_r(NULL, ",", &saveptr);
}
if (optionError) {
lprintf(LOG_NOTICE, "Legal options settings are:");
lprintf(LOG_NOTICE, " %-22s: %s",
"help",
"print this message");
for (op = options; op->name; ++op) {
lprintf(LOG_NOTICE, " %-22s: %s", op->name, op->desc);
}
return false;
}
return true;
}
int
ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int rc = 0;
int rc = -1;
if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
if (!argc || !strcmp(argv[0], "help")) {
lprintf(LOG_NOTICE, "Chassis Commands:\n"
" status, power, policy, restart_cause\n"
" poh, identify, selftest,\n"
" bootdev, bootparam, bootmbox");
}
else if (strncmp(argv[0], "status", 6) == 0) {
else if (!strcmp(argv[0], "status")) {
rc = ipmi_chassis_status(intf);
}
else if (strncmp(argv[0], "selftest", 8) == 0) {
else if (!strcmp(argv[0], "selftest")) {
rc = ipmi_chassis_selftest(intf);
}
else if (strncmp(argv[0], "power", 5) == 0) {
else if (!strcmp(argv[0], "power")) {
uint8_t ctl = 0;
if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
if (argc < 2 || !strcmp(argv[1], "help")) {
lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft");
return 0;
rc = 0;
goto out;
}
if (strncmp(argv[1], "status", 6) == 0) {
if (!strcmp(argv[1], "status")) {
rc = ipmi_chassis_print_power_status(intf);
return rc;
goto out;
}
if ((strncmp(argv[1], "up", 2) == 0) || (strncmp(argv[1], "on", 2) == 0))
if (!strcmp(argv[1], "up") ||
!strcmp(argv[1], "on"))
{
ctl = IPMI_CHASSIS_CTL_POWER_UP;
else if ((strncmp(argv[1], "down", 4) == 0) || (strncmp(argv[1], "off", 3) == 0))
}
else if (!strcmp(argv[1], "down") ||
!strcmp(argv[1], "off"))
{
ctl = IPMI_CHASSIS_CTL_POWER_DOWN;
else if (strncmp(argv[1], "cycle", 5) == 0)
}
else if (!strcmp(argv[1], "cycle"))
ctl = IPMI_CHASSIS_CTL_POWER_CYCLE;
else if (strncmp(argv[1], "reset", 5) == 0)
else if (!strcmp(argv[1], "reset"))
ctl = IPMI_CHASSIS_CTL_HARD_RESET;
else if (strncmp(argv[1], "diag", 4) == 0)
else if (!strcmp(argv[1], "diag"))
ctl = IPMI_CHASSIS_CTL_PULSE_DIAG;
else if ((strncmp(argv[1], "acpi", 4) == 0) || (strncmp(argv[1], "soft", 4) == 0))
else if (!strcmp(argv[1], "acpi") ||
!strcmp(argv[1], "soft"))
{
ctl = IPMI_CHASSIS_CTL_ACPI_SOFT;
}
else {
lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[1]);
return -1;
goto out;
}
rc = ipmi_chassis_power_control(intf, ctl);
}
else if (strncmp(argv[0], "identify", 8) == 0) {
else if (!strcmp(argv[0], "identify")) {
if (argc < 2) {
rc = ipmi_chassis_identify(intf, NULL);
}
else if (strncmp(argv[1], "help", 4) == 0) {
else if (!strcmp(argv[1], "help")) {
lprintf(LOG_NOTICE, "chassis identify <interval>");
lprintf(LOG_NOTICE, " default is 15 seconds");
lprintf(LOG_NOTICE, " 0 to turn off");
@ -1614,14 +1999,14 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
rc = ipmi_chassis_identify(intf, argv[1]);
}
}
else if (strncmp(argv[0], "poh", 3) == 0) {
else if (!strcmp(argv[0], "poh")) {
rc = ipmi_chassis_poh(intf);
}
else if (strncmp(argv[0], "restart_cause", 13) == 0) {
else if (!strcmp(argv[0], "restart_cause")) {
rc = ipmi_chassis_restart_cause(intf);
}
else if (strncmp(argv[0], "policy", 4) == 0) {
if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
else if (!strcmp(argv[0], "policy")) {
if (argc < 2 || !strcmp(argv[1], "help")) {
lprintf(LOG_NOTICE, "chassis policy <state>");
lprintf(LOG_NOTICE, " list : return supported policies");
lprintf(LOG_NOTICE, " always-on : turn on when power is restored");
@ -1629,13 +2014,13 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
lprintf(LOG_NOTICE, " always-off : stay off after power is restored");
} else {
uint8_t ctl;
if (strncmp(argv[1], "list", 4) == 0)
if (!strcmp(argv[1], "list"))
ctl = IPMI_CHASSIS_POLICY_NO_CHANGE;
else if (strncmp(argv[1], "always-on", 9) == 0)
else if (!strcmp(argv[1], "always-on"))
ctl = IPMI_CHASSIS_POLICY_ALWAYS_ON;
else if (strncmp(argv[1], "previous", 8) == 0)
else if (!strcmp(argv[1], "previous"))
ctl = IPMI_CHASSIS_POLICY_PREVIOUS;
else if (strncmp(argv[1], "always-off", 10) == 0)
else if (!strcmp(argv[1], "always-off"))
ctl = IPMI_CHASSIS_POLICY_ALWAYS_OFF;
else {
lprintf(LOG_ERR, "Invalid chassis policy: %s", argv[1]);
@ -1644,22 +2029,22 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
rc = ipmi_chassis_power_policy(intf, ctl);
}
}
else if (strncmp(argv[0], "bootparam", 9) == 0) {
if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) {
else if (!strcmp(argv[0], "bootparam")) {
if (argc < 3 || !strcmp(argv[1], "help")) {
lprintf(LOG_NOTICE, "bootparam get <param #>");
ipmi_chassis_set_bootflag_help();
}
else {
if (strncmp(argv[1], "get", 3) == 0) {
if (!strcmp(argv[1], "get")) {
rc = ipmi_chassis_get_bootparam(intf,
argc - 2,
argv + 2,
0);
}
else if (strncmp(argv[1], "set", 3) == 0) {
else if (!strcmp(argv[1], "set")) {
unsigned char set_flag=0;
unsigned char clr_flag=0;
if (strncmp(argv[2], "help", 4) == 0 ||
if (!strcmp(argv[2], "help") ||
argc < 4 || (argc >= 4 &&
strncmp(argv[2], "bootflag", 8) != 0)) {
ipmi_chassis_set_bootflag_help();
@ -1677,8 +2062,8 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
lprintf(LOG_NOTICE, "bootparam get|set <option> [value ...]");
}
}
else if (strncmp(argv[0], "bootdev", 7) == 0) {
if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) {
else if (!strcmp(argv[0], "bootdev")) {
if (argc < 2 || !strcmp(argv[1], "help")) {
lprintf(LOG_NOTICE, "bootdev <device> [clear-cmos=yes|no]");
lprintf(LOG_NOTICE, "bootdev <device> [options=help,...]");
lprintf(LOG_NOTICE, " none : Do not change boot device order");
@ -1690,108 +2075,31 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
lprintf(LOG_NOTICE, " bios : Force boot into BIOS Setup");
lprintf(LOG_NOTICE, " floppy: Force boot from Floppy/primary removable media");
} else {
if (argc < 3)
rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
else if (strncmp(argv[2], "clear-cmos=", 11) == 0) {
if (strncmp(argv[2]+11, "yes", 3) == 0) {
uint8_t flags[5] = {0, (1<<7), 0, 0, 0};
rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
} else
rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
}
else if (strncmp(argv[2], "options=", 8) == 0) {
char *token;
char *saveptr = NULL;
int optionError = 0;
unsigned char flags[5];
static struct {
char *name;
int i;
unsigned char mask;
unsigned char value;
char *desc;
} options[] = {
/* data 1 */
{"valid", 0, (1<<7), (1<<7),
"Boot flags valid"},
{"persistent", 0, (1<<6), (1<<6),
"Changes are persistent for all future boots"},
{"efiboot", 0, (1<<5), (1<<5),
"Extensible Firmware Interface Boot (EFI)"},
/* data 2 */
{"clear-cmos", 1, (1<<7), (1<<7),
"CMOS clear"},
{"lockkbd", 1, (1<<6), (1<<6),
"Lock Keyboard"},
/* data2[5:2] is parsed elsewhere */
{"screenblank", 1, (1<<1), (1<<1),
"Screen Blank"},
{"lockoutreset", 1, (1<<0), (1<<0),
"Lock out Resetbuttons"},
/* data 3 */
{"lockout_power", 2, (1<<7), (1<<7),
"Lock out (power off/sleep request) via Power Button"},
{"verbose=default", 2, (3<<5), (0<<5),
"Request quiet BIOS display"},
{"verbose=no", 2, (3<<5), (1<<5),
"Request quiet BIOS display"},
{"verbose=yes", 2, (3<<5), (2<<5),
"Request verbose BIOS display"},
{"force_pet", 2, (1<<4), (1<<4),
"Force progress event traps"},
{"upw_bypass", 2, (1<<3), (1<<3),
"User password bypass"},
{"lockout_sleep", 2, (1<<2), (1<<2),
"Log Out Sleep Button"},
{"cons_redirect=default", 2, (3<<0), (0<<0),
"Console redirection occurs per BIOS configuration setting"},
{"cons_redirect=skip", 2, (3<<0), (1<<0),
"Suppress (skip) console redirection if enabled"},
{"cons_redirect=enable", 2, (3<<0), (2<<0),
"Suppress (skip) console redirection if enabled"},
/* data 4 */
/* data4[7:4] reserved */
/* data4[3] BIOS Shared Mode Override, not implemented here */
/* data4[2:0] BIOS Mux Control Override, not implemented here */
static const char *kw = "options=";
static const int kw_len = 8;
char *optstr = NULL;
uint8_t flags[BF_BYTE_COUNT];
bool use_flags = false;
/* data5 reserved */
if (argc >= 3) {
if (!strcmp(argv[2], "clear-cmos=yes")) {
/* Exclusive clear-cmos, no other flags */
optstr = "clear-cmos";
}
else if (!strncmp(argv[2], kw, kw_len)) {
optstr = argv[2] + kw_len;
}
}
if (optstr) {
if (!bootdev_parse_options(optstr, flags))
goto out;
{NULL} /* End marker */
}, *op;
memset(&flags[0], 0, sizeof(flags));
token = strtok_r(argv[2] + 8, ",", &saveptr);
while (token) {
if (strcmp(token, "help") == 0) {
optionError = 1;
break;
use_flags = true;
}
for (op = options; op->name; ++op) {
if (strcmp(token, op->name) == 0) {
flags[op->i] &= op->mask;
flags[op->i] |= op->value;
break;
}
}
if (!op->name) {
/* Option not found */
optionError = 1;
lprintf(LOG_ERR, "Invalid option: %s", token);
}
token = strtok_r(NULL, ",", &saveptr);
}
if (optionError) {
lprintf(LOG_NOTICE, "Legal options settings are:");
lprintf(LOG_NOTICE, "\thelp:\tprint this message");
for (op = options; op->name; ++op) {
lprintf(LOG_NOTICE, "\t%s:\t%s", op->name, op->desc);
}
return (-1);
}
rc = ipmi_chassis_set_bootdev(intf, argv[1], flags);
}
else
rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
rc = ipmi_chassis_set_bootdev(intf, argv[1],
use_flags
? flags
: NULL);
}
}
else if (!strcmp(argv[0], "bootmbox")) {
@ -1799,8 +2107,8 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
}
else {
lprintf(LOG_ERR, "Invalid chassis command: %s", argv[0]);
return -1;
}
out:
return rc;
}

View File

@ -450,7 +450,7 @@ const struct dcmi_cmd nm_policy_options[] = {
{ 0x02, "disable", "" },
{ 0x03, "domain", "" },
{ 0x04, "inlet", "inlet air temp full limiting (SCRAM)" },
{ 0x06, "correction" "auto, soft, hard" },
{ 0x06, "correction","auto, soft, hard" },
{ 0x08, "power", "power limit in watts" },
{ 0x09, "trig_lim", "time to send alert" },
{ 0x0A, "stats", "moving window averaging time" },

View File

@ -52,6 +52,14 @@
#include <ipmitool/ipmi_event.h>
#include <ipmitool/ipmi_sdr.h>
static
inline
bool
is_system(const struct channel_info_t *chinfo)
{
return (IPMI_CHANNEL_MEDIUM_SYSTEM == chinfo->medium
|| CH_SYSTEM == chinfo->channel);
}
static void
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
@ -61,7 +69,8 @@ ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
memset(&sel_event, 0, sizeof(struct sel_event_record));
sel_event.record_id = 0;
sel_event.sel_type.standard_type.gen_id = 2;
htoipmi16(EVENT_GENERATOR(SMS, 0),
(void *)&sel_event.sel_type.standard_type.gen_id);
sel_event.sel_type.standard_type.evm_rev = pmsg->evm_rev;
sel_event.sel_type.standard_type.sensor_type = pmsg->sensor_type;
@ -83,28 +92,34 @@ ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * em
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[8];
uint8_t chmed;
uint8_t rqdata[PLATFORM_EVENT_DATA_LEN_MAX];
uint8_t *rqdata_start = rqdata;
struct channel_info_t chinfo;
memset(&req, 0, sizeof(req));
memset(rqdata, 0, 8);
memset(rqdata, 0, sizeof(rqdata));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = 0x02;
req.msg.cmd = IPMI_CMD_PLATFORM_EVENT;
req.msg.data = rqdata;
req.msg.data_len = PLATFORM_EVENT_DATA_LEN_NON_SI;
chmed = ipmi_current_channel_medium(intf);
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
/* system interface, need extra generator ID */
req.msg.data_len = 8;
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
memcpy(rqdata+1, emsg, sizeof(struct platform_event_msg));
ipmi_current_channel_info(intf, &chinfo);
if (chinfo.channel == CH_UNKNOWN) {
lprintf(LOG_ERR, "Failed to send the platform event "
"via an unknown channel");
return -3;
}
else {
req.msg.data_len = 7;
memcpy(rqdata, emsg, sizeof(struct platform_event_msg));
if (is_system(&chinfo)) {
/* system interface, need extra generator ID, see Fig. 29-2 */
req.msg.data_len = PLATFORM_EVENT_DATA_LEN_SI;
rqdata[0] = EVENT_GENERATOR(SMS, 0);
rqdata_start++;
}
memcpy(rqdata_start, emsg, sizeof(struct platform_event_msg));
ipmi_event_msg_print(intf, emsg);
rsp = intf->sendrecv(intf, &req);
@ -484,43 +499,30 @@ static int
ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
{
FILE * fp;
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct sel_event_record sel_event;
uint8_t rqdata[8];
/* For ease of filling in from file data */
union {
struct platform_event_msg emsg;
uint8_t bytes[sizeof(struct platform_event_msg)];
} __attribute__ ((packed)) rqdata;
char buf[1024];
char * ptr, * tok;
int i, j;
uint8_t chmed;
int rc = 0;
if (!file)
return -1;
memset(rqdata, 0, 8);
/* setup Platform Event Message command */
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = 0x02;
req.msg.data = rqdata;
req.msg.data_len = 7;
chmed = ipmi_current_channel_medium(intf);
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
/* system interface, need extra generator ID */
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
req.msg.data_len = 8;
}
fp = ipmi_open_file_read(file);
if (!fp)
return -1;
while (feof(fp) == 0) {
size_t count = 0;
if (!fgets(buf, 1024, fp))
continue;
/* Each line is a new event */
memset(&rqdata, 0, sizeof(rqdata));
/* clip off optional comment tail indicated by # */
ptr = strchr(buf, '#');
if (ptr)
@ -540,49 +542,28 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
/* parse the event, 7 bytes with optional comment */
/* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */
i = 0;
tok = strtok(ptr, " ");
while (tok) {
if (i == 7)
if (count == sizeof(struct platform_event_msg))
break;
if (0 > str2uchar(tok, &rqdata.bytes[count])) {
lprintf(LOG_ERR, "Invalid token in file: [%s]", tok);
rc = -1;
break;
j = i++;
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
j++;
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
tok = strtok(NULL, " ");
}
if (i < 7) {
tok = strtok(NULL, " ");
++count;
}
if (count < sizeof(struct platform_event_msg)) {
lprintf(LOG_ERR, "Invalid Event: %s",
buf2str(rqdata, sizeof(rqdata)));
buf2str(rqdata.bytes, sizeof(rqdata.bytes)));
continue;
}
memset(&sel_event, 0, sizeof(struct sel_event_record));
sel_event.record_id = 0;
sel_event.sel_type.standard_type.gen_id = 2;
j = (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) ? 1 : 0;
sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
sel_event.sel_type.standard_type.event_type = rqdata[j] & 0x7f;
sel_event.sel_type.standard_type.event_dir = (rqdata[j++] & 0x80) >> 7;
sel_event.sel_type.standard_type.event_data[0] = rqdata[j++];
sel_event.sel_type.standard_type.event_data[1] = rqdata[j++];
sel_event.sel_type.standard_type.event_data[2] = rqdata[j++];
ipmi_sel_print_std_entry(intf, &sel_event);
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
lprintf(LOG_ERR, "Platform Event Message command failed");
rc = -1;
}
else if (rsp->ccode) {
lprintf(LOG_ERR, "Platform Event Message command failed: %s",
val2str(rsp->ccode, completion_code_vals));
rc = -1;
}
/* Now actually send it, failures will be logged by the sender */
rc = ipmi_send_platform_event(intf, &rqdata.emsg);
if (IPMI_CC_OK != rc)
break;
}
fclose(fp);

View File

@ -111,12 +111,6 @@ static inline bool fru_cc_rq2big(int code) {
int
ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id);
/* From src/plugins/ipmi_intf.c: */
void
ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size);
void
ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size);
extern int verbose;
static void ipmi_fru_read_to_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
@ -669,7 +663,10 @@ int
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
uint32_t off = offset, tmp, finish;
uint32_t off = offset;
uint32_t tmp;
uint32_t finish;
uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@ -682,10 +679,12 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
length = finish - offset;
}
memset(&req, 0, sizeof(req));
@ -721,6 +720,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
}
size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@ -762,9 +762,18 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
if(rsp->data_len < 1
|| tmp > rsp->data_len - 1
|| tmp > size_left_in_buffer)
{
printf(" Not enough buffer size");
return -1;
}
memcpy(frubuf, rsp->data + 1, tmp);
off += tmp;
frubuf += tmp;
size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
* still attempts to parse what was returned */
@ -797,7 +806,9 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
static uint32_t fru_data_rqst_size = 20;
uint32_t off = offset, tmp, finish;
uint32_t off = offset;
uint32_t tmp, finish;
uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@ -810,10 +821,12 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
length = finish - offset;
}
memset(&req, 0, sizeof(req));
@ -828,6 +841,8 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
if (fru->access && fru_data_rqst_size > 16)
#endif
fru_data_rqst_size = 16;
size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@ -859,8 +874,16 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
if(rsp->data_len < 1
|| tmp > rsp->data_len - 1
|| tmp > size_left_in_buffer)
{
printf(" Not enough buffer size");
return -1;
}
memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
off += tmp;
size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
@ -3019,7 +3042,6 @@ __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
int
ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
{
char desc[17];
uint8_t bridged_request = 0;
uint32_t save_addr;
uint32_t save_channel;
@ -3054,10 +3076,10 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
fru->device_id == 0)
return 0;
memset(desc, 0, sizeof(desc));
memcpy(desc, fru->id_string, fru->id_code & 0x01f);
desc[fru->id_code & 0x01f] = 0;
printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
printf("FRU Device Description : %.*s (ID %d)\n"
, SDR_ID_STRLEN(fru)
, fru->id_string
, fru->device_id);
switch (fru->dev_type_modifier) {
case 0x00:
@ -3169,7 +3191,9 @@ ipmi_fru_print_all(struct ipmi_intf * intf)
/* set new target address to satellite controller */
intf->target_addr = mc->dev_slave_addr;
printf("FRU Device Description : %-16s\n", mc->id_string);
printf("FRU Device Description : %.*s\n"
, SDR_ID_STRLEN(fru)
, fru->id_string);
/* print the FRU by issuing FRU commands to the satellite */
/* controller. */

View File

@ -48,10 +48,6 @@
# include <config.h>
#endif
/* From src/plugins/ipmi_intf.c: */
uint16_t
ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf);
extern int verbose;
int HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename,

View File

@ -1260,7 +1260,7 @@ ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string)
rc = 0;
goto out;
}
if (IPMI_LANP_IS_VLAN_VALID(id)) {
if (!IPMI_LANP_IS_VLAN_VALID(id)) {
lprintf(LOG_ERR,
"Retrieved VLAN ID %i is out of "
"range <%d..%d>.",
@ -1285,7 +1285,7 @@ ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string)
goto out;
}
if (IPMI_LANP_IS_VLAN_VALID(id)) {
if (!IPMI_LANP_IS_VLAN_VALID(id)) {
lprintf(LOG_NOTICE,
"VLAN ID must be between %d and %d.",
IPMI_LANP_VLAN_ID_MIN,
@ -1865,7 +1865,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new ipaddr */
memcpy(data+3, temp, 4);
printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert,
@ -1880,7 +1880,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new macaddr */
memcpy(data+7, temp, 6);
printf("Setting LAN Alert %d MAC Address to "
@ -1894,7 +1894,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "def", 3) == 0 ||
strncasecmp(argv[1], "default", 7) == 0) {
@ -1920,7 +1920,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "on", 2) == 0 ||
strncasecmp(argv[1], "yes", 3) == 0) {
@ -1945,7 +1945,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "pet", 3) == 0) {
printf("Setting LAN Alert %d destination to PET Trap\n", alert);
@ -1973,7 +1973,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[2]) != 0) {
lprintf(LOG_ERR, "Invalid time: %s", argv[1]);
@ -1989,7 +1989,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (!p) {
return (-1);
}
memcpy(data, p->data, p->data_len);
memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[3]) != 0) {
lprintf(LOG_ERR, "Invalid retry: %s", argv[1]);

View File

@ -844,6 +844,12 @@ ipmi_main(int argc, char ** argv,
/* setup log */
log_init(progname, 0, verbose);
/* load the IANA PEN registry */
if (ipmi_oem_info_init()) {
lprintf(LOG_ERR, "Failed to initialize the OEM info dictionary");
goto out_free;
}
/* run OEM setup if found */
if (oemtype &&
ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) {
@ -1063,6 +1069,8 @@ ipmi_main(int argc, char ** argv,
devfile = NULL;
}
ipmi_oem_info_free();
return rc;
}

View File

@ -219,10 +219,6 @@ static const char *sensor_type_desc[] = {
void printf_sdr_usage();
/* From src/plugins/ipmi_intf.c: */
uint16_t
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf);
/** ipmi_sdr_get_unit_string - return units for base/modifier
*
* @param[in] pct Indicates that units are a percentage
@ -1578,22 +1574,14 @@ ipmi_sdr_read_sensor_value(struct ipmi_intf *intf,
/* Initialize to reading valid value of zero */
memset(&sr, 0, sizeof(sr));
sr.raw = sensor;
switch (sdr_record_type) {
unsigned int idlen;
case (SDR_RECORD_TYPE_FULL_SENSOR):
sr.full = (struct sdr_record_full_sensor *)sensor;
idlen = sr.full->id_code & 0x1f;
idlen = idlen < sizeof(sr.s_id) ?
idlen : sizeof(sr.s_id) - 1;
memcpy(sr.s_id, sr.full->id_string, idlen);
case SDR_RECORD_TYPE_FULL_SENSOR:
SDR_ID_TO_CSTRING(sr.s_id, sr.full);
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
sr.compact = (struct sdr_record_compact_sensor *)sensor;
idlen = sr.compact->id_code & 0x1f;
idlen = idlen < sizeof(sr.s_id) ?
idlen : sizeof(sr.s_id) - 1;
memcpy(sr.s_id, sr.compact->id_string, idlen);
SDR_ID_TO_CSTRING(sr.s_id, sr.compact);
break;
default:
return NULL;
@ -2252,13 +2240,12 @@ int
ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
struct sdr_record_eventonly_sensor *sensor)
{
char desc[17];
char desc[SDR_ID_STRING_MAX + 1];
if (!sensor)
return -1;
memset(desc, 0, sizeof (desc));
snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
SDR_ID_TO_CSTRING(desc, sensor);
if (verbose) {
printf("Sensor ID : %s (0x%x)\n",
@ -2301,13 +2288,12 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
int
ipmi_sdr_print_sensor_mc_locator(struct sdr_record_mc_locator *mc)
{
char desc[17];
char desc[SDR_ID_STRING_MAX + 1];
if (!mc)
return -1;
memset(desc, 0, sizeof (desc));
snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
SDR_ID_TO_CSTRING(desc, mc);
if (verbose == 0) {
if (csv_output)
@ -2395,10 +2381,12 @@ ipmi_sdr_print_sensor_mc_locator(struct sdr_record_mc_locator *mc)
int
ipmi_sdr_print_sensor_generic_locator(struct sdr_record_generic_locator *dev)
{
char desc[17];
char desc[SDR_ID_STRING_MAX + 1];
memset(desc, 0, sizeof (desc));
snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
if (!dev)
return -1;
SDR_ID_TO_CSTRING(desc, dev);
if (!verbose) {
if (csv_output)
@ -2450,10 +2438,12 @@ ipmi_sdr_print_sensor_generic_locator(struct sdr_record_generic_locator *dev)
int
ipmi_sdr_print_sensor_fru_locator(struct sdr_record_fru_locator *fru)
{
char desc[17];
char desc[SDR_ID_STRING_MAX + 1];
memset(desc, 0, sizeof (desc));
snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
if (!fru)
return -1;
SDR_ID_TO_CSTRING(desc, fru);
if (!verbose) {
if (csv_output)
@ -2613,17 +2603,20 @@ ipmi_sdr_print_sensor_oem(struct sdr_record_oem *oem)
return rc;
}
/* ipmi_sdr_print_name_from_rawentry - Print SDR name from raw data
/**
* Get SDR record name from raw data
*
* @type: sensor type
* @raw: raw sensor data
* @param[in] type SDR record type
* @param[in] raw raw SDR record data
* @param[out] buf The SDR record description target buffer
* @param[in] len The length of the target buffer
*
* returns 0 on success
* returns -1 on error
* @returns Error status
* @retval 0 Success
* @retval -1 Error
*/
int
ipmi_sdr_print_name_from_rawentry(uint16_t id,
uint8_t type, uint8_t *raw)
sdr_get_name_from_rawentry(uint8_t type, void *raw, char *buf, size_t len)
{
union {
struct sdr_record_full_sensor *full;
@ -2634,39 +2627,50 @@ ipmi_sdr_print_name_from_rawentry(uint16_t id,
struct sdr_record_mc_locator *mcloc;
struct sdr_record_entity_assoc *entassoc;
struct sdr_record_oem *oem;
void *raw;
} record;
int rc =0;
char desc[17];
memset(desc, ' ', sizeof (desc));
char desc[SDR_ID_STRING_MAX + 1] = { 0 };
record.raw = raw;
switch ( type) {
/* Sensor records */
case SDR_RECORD_TYPE_FULL_SENSOR:
record.full = (struct sdr_record_full_sensor *) raw;
snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
(const char *)record.full->id_string);
SDR_ID_TO_CSTRING(desc, record.full);
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
record.compact = (struct sdr_record_compact_sensor *) raw ;
snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s",
(const char *)record.compact->id_string);
SDR_ID_TO_CSTRING(desc, record.compact);
break;
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
record.eventonly = (struct sdr_record_eventonly_sensor *) raw ;
snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s",
(const char *)record.eventonly->id_string);
SDR_ID_TO_CSTRING(desc, record.eventonly);
break;
/* Device locator records */
case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR:
SDR_ID_TO_CSTRING(desc, record.genloc);
break;
case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
SDR_ID_TO_CSTRING(desc, record.fruloc);
break;
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
record.mcloc = (struct sdr_record_mc_locator *) raw ;
snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s",
(const char *)record.mcloc->id_string);
SDR_ID_TO_CSTRING(desc, record.mcloc);
break;
/* All other records don't have the id_string field */
default:
rc = -1;
break;
}
lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
memcpy(buf, desc, __min(sizeof(buf), len));
return rc;
}

View File

@ -250,6 +250,7 @@ sdrr_get_records(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr,
while ((header = ipmi_sdr_get_next_header(intf, itr))) {
struct sdr_record_list *sdrr;
char desc[SDR_ID_STRING_MAX + 1];
sdrr = malloc(sizeof (struct sdr_record_list));
if (!sdrr) {
@ -263,7 +264,8 @@ sdrr_get_records(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr,
sdrr->type = header->type;
sdrr->length = header->length;
sdrr->raw = ipmi_sdr_get_record(intf, header, itr);
(void)ipmi_sdr_print_name_from_rawentry(sdrr->id, sdrr->type,sdrr->raw);
(void)sdr_get_name_from_rawentry(sdrr->type, sdrr->raw, desc, sizeof(desc));
lprintf(LOG_INFO, "ID: 0x%04x , NAME: %s", sdrr->id, desc);
/* put in the record queue */
if (!queue->head)

View File

@ -454,10 +454,10 @@ get_kontron_evt_desc(struct ipmi_intf *__UNUSED__(intf), struct sel_event_record
}
char *
get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
get_viking_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
{
/*
* Newisys OEM event descriptions can be retrieved through an
* Viking OEM event descriptions can be retrieved through an
* OEM IPMI command.
*/
struct ipmi_rs * rsp;
@ -495,17 +495,17 @@ get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
/* Verify our response before we use it */
if (rsp->data_len < 5)
{
lprintf(LOG_ERR, "Newisys OEM response too short");
lprintf(LOG_ERR, "Viking OEM response too short");
return NULL;
}
else if (rsp->data_len != (4 + rsp->data[3]))
{
lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
lprintf(LOG_ERR, "Viking OEM response has unexpected length");
return NULL;
}
else if (IPM_DEV_MANUFACTURER_ID(rsp->data) != IPMI_OEM_NEWISYS)
else if (IPM_DEV_MANUFACTURER_ID(rsp->data) != IPMI_OEM_VIKING)
{
lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
lprintf(LOG_ERR, "Viking OEM response has unexpected length");
return NULL;
}
@ -1205,8 +1205,8 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
switch (ipmi_get_oem(intf))
{
case IPMI_OEM_NEWISYS:
desc = get_newisys_evt_desc(intf, rec);
case IPMI_OEM_VIKING:
desc = get_viking_evt_desc(intf, rec);
break;
case IPMI_OEM_KONTRON:
desc = get_kontron_evt_desc(intf, rec);
@ -2743,6 +2743,7 @@ ipmi_sel_set_time(struct ipmi_intf * intf, const char * time_string)
struct ipmi_rs *rsp;
struct ipmi_rq req;
struct tm tm = {0};
uint8_t msg_data[4] = {0};
time_t t;
const char *time_format = "%x %X"; /* Use locale-defined format */
@ -2787,8 +2788,9 @@ ipmi_sel_set_time(struct ipmi_intf * intf, const char * time_string)
* At this point `t` is UTC. Convert it to LE and send.
*/
req.msg.data = msg_data;
htoipmi32(t, req.msg.data);
req.msg.data_len = 4;
req.msg.data_len = sizeof(msg_data);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {

View File

@ -309,8 +309,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
}
else
{
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
memcpy(&session_info, rsp->data,
__min(rsp->data_len, sizeof(session_info)));
print_session_info(&session_info,
__min(rsp->data_len, sizeof(session_info)));
}
break;
@ -341,8 +343,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
break;
}
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
memcpy(&session_info, rsp->data,
__min(rsp->data_len, sizeof(session_info)));
print_session_info(&session_info,
__min(rsp->data_len, sizeof(session_info)));
} while (i <= session_info.session_slot_count);
break;

File diff suppressed because it is too large Load Diff

View File

@ -434,7 +434,7 @@ print_user_usage(void)
lprintf(LOG_NOTICE,
" set name <user id> <username>");
lprintf(LOG_NOTICE,
" set password <user id> [<password> <16|20>]");
" set password <user id> [<password> [<16|20>]]");
lprintf(LOG_NOTICE,
" disable <user id>");
lprintf(LOG_NOTICE,
@ -626,12 +626,17 @@ ipmi_user_mod(struct ipmi_intf *intf, int argc, char **argv)
return 0;
}
#define USER_PW_IPMI15_LEN 16 /* IPMI 1.5 only allowed for 16 bytes */
#define USER_PW_IPMI20_LEN 20 /* IPMI 2.0 allows for 20 bytes */
#define USER_PW_MAX_LEN USER_PW_IPMI20_LEN
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 password_type = USER_PW_IPMI15_LEN;
size_t password_len;
uint8_t user_id = 0;
if (is_ipmi_user_id(argv[2], &user_id)) {
return (-1);
@ -640,45 +645,56 @@ ipmi_user_password(struct ipmi_intf *intf, int argc, char **argv)
if (argc == 3) {
/* We need to prompt for a password */
char *tmp;
size_t tmplen;
password = ask_password(user_id);
if (!password) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return (-1);
}
tmp = ask_password(user_id);
tmplen = strnlen(tmp, USER_PW_MAX_LEN + 1);
if (!tmp) {
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.");
if (strncmp(password, tmp, tmplen)) {
lprintf(LOG_ERR, "Passwords do not match or are "
"longer than %d", USER_PW_MAX_LEN);
return (-1);
}
} 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);
}
} else {
password_type = 16;
}
}
if (!password) {
lprintf(LOG_ERR, "Unable to parse password argument.");
return (-1);
} else if (strlen(password) > 20) {
lprintf(LOG_ERR, "Password is too long (> 20 bytes)");
}
password_len = strnlen(password, USER_PW_MAX_LEN + 1);
if (argc > 4) {
if ((str2uchar(argv[4], &password_type) != 0)
|| (password_type != USER_PW_IPMI15_LEN
&& password_type != USER_PW_IPMI20_LEN))
{
lprintf(LOG_ERR, "Invalid password length '%s'",
argv[4]);
return (-1);
}
} else if (password_len > USER_PW_IPMI15_LEN) {
password_type = USER_PW_IPMI20_LEN;
}
if (password_len > password_type) {
lprintf(LOG_ERR, "Password is too long (> %d bytes)",
password_type);
return (-1);
}
ccode = _ipmi_set_user_password(intf, user_id,
IPMI_PASSWORD_SET_PASSWORD, password,
password_type > 16);
password_type > USER_PW_IPMI15_LEN);
if (eval_ccode(ccode) != 0) {
lprintf(LOG_ERR, "Set User Password command failed (user %d)",
user_id);

View File

@ -31,7 +31,7 @@
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
AM_CPPFLAGS = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_dbus.la
noinst_LTLIBRARIES = @INTF_DBUS_LIB@

View File

@ -761,12 +761,6 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
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
*/
@ -793,6 +787,9 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
offset = 0;
payload_start = 0;
payload_size = extra_data_length;
} else {
rsp->data_len = 0;
}