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 2693 additions and 616 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
@ -473,36 +477,94 @@ Force boot into BIOS Setup.
Force boot from Floppy/primary removable media.
.RE
.TP
\fIbootmbox\fP \fIget\fP [text] [block <\fBblock#\fP>]
Read the Boot Initiator Mailbox in hex dump or in text mode.
By default the whole mailbox is read. If block number is specified,
that particular block is read. For block 0 or when the whole
mailbox is read, the Boot Initiator IANA Enterprise Number and
the corresponding enterprise name are printed.
.TP
\fIbootmbox\fP \fIset\fP text [block <\fBblock#\fP>] <\fBIANA_PEN\fP> "<\fBdata_string\fP>"
Write the specified <block> or the entire Boot Initiator Mailbox in text mode.
It is required to specify a decimal IANA Enterprise Number recognized
by the boot initiator on the target system. Refer to your target system
manufacturer for details. The rest of the arguments are a text string.
When single block write is requested, the total length of <data> may not
exceed 13 bytes for block 0, or 16 bytes otherwise.
.TP
\fIbootmbox\fP \fIset\fP [block <\fBblock#\fP>] <\fBIANA_PEN\fP> <\fBdata_byte\fP> [<\fBdata_byte\fP> ...]
Same as above, but the arguments after IANA PEN are separate
data byte values separated by spaces.
.TP
\fIbootparam\fP
\fIbootparam\fP \fIget\fP <\fBopt_id\fR> [<\fBopt_param\fR>]
Get value of system boot option number <\fBopt_id\fR>. Some boot
options (e.g. option 7) can also take an optional numeric parameter.
.TP
\fIbootparam\fP \fIset\fP bootflag <\fBdevice\fR> [options=...]
Set a boot flag. Valid devices are:
.RS
.TP
\fIforce_pxe\fP
.IP \fIforce_pxe\fP
Force PXE boot
.TP
\fIforce_disk\fP
.IP \fIforce_disk\fP
Force boot from default Hard-drive
.TP
\fIforce_safe\fP
.IP \fIforce_safe\fP
Force boot from default Hard-drive, request Safe Mode
.TP
\fIforce_diag\fP
.IP \fIforce_diag\fP
Force boot from Diagnostic Partition
.TP
\fIforce_cdrom\fP
.IP \fIforce_cdrom\fP
Force boot from CD/DVD
.TP
\fIforce_bios\fP
.IP \fIforce_bios\fP
Force boot into BIOS Setup
.PP
Valid options are:
.IP \fIPEF\fP
Clear valid bit on reset/power cycle cause by PEF
.IP \fItimeout\fP
Automatically clear boot flag valid bit on timeout
.IP \fIwatchdog\fP
Clear valid bit on reset/power cycle cause by watchdog
.IP \fIreset\fP
Clear valid bit on push button reset/soft reset
.IP \fIpower\fP
Clear valid bit on power up via power push button or wake event
.RE
.TP
\fIselftest\fP
Get the chassis self-test results
.RE
.TP
\fIdcmi\fP
@ -3468,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>
@ -3759,7 +3822,16 @@ Chassis Power is on
> ipmitool \-I lan \-H 1.2.3.4 \-f passfile chassis power 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

@ -38,6 +38,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* For free() */
#include <stdbool.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@ -79,8 +80,12 @@ struct oemvalstr {
const char * str;
};
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 *
specific_val2str(uint32_t val,
const struct valstr *specific,
const struct valstr *generic);
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);
@ -92,6 +97,8 @@ int str2ushort(const char * str, uint16_t * ushrt_ptr);
int str2char(const char * str, int8_t * chr_ptr);
int str2uchar(const char * str, uint8_t * uchr_ptr);
bool args2buf(int argc, char *argv[], uint8_t *out, size_t len);
int eval_ccode(const int ccode);
int is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr);
@ -99,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);
@ -166,6 +177,13 @@ static inline uint32_t ipmi24toh(void *ipmi24)
return h;
}
static inline void htoipmi24(uint32_t h, uint8_t *ipmi)
{
ipmi[0] = h & 0xFF; /* LSB */
ipmi[1] = (h >> 8) & 0xFF;
ipmi[2] = (h >> 16) & 0xFF; /* MSB */
}
static inline uint32_t ipmi32toh(void *ipmi32)
{
uint8_t *ipmi = ipmi32;

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 */
struct sdr_record_full_sensor *full;
struct sdr_record_compact_sensor *compact;
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

@ -319,26 +319,74 @@ mac2str(const uint8_t *buf)
return buf2str_extended(buf, 6, ":");
}
const char * val2str(uint16_t val, const struct valstr *vs)
/**
* Find the index of value in a valstr array
*
* @param[in] val The value to search for
* @param[in] vs The valstr array to search in
* @return >=0 The index into \p vs
* @return -1 Error: value \p val was not found in \p vs
*/
static
inline
off_t find_val_idx(uint32_t val, const struct valstr *vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].str; i++) {
if (vs[i].val == val)
return vs[i].str;
if (vs) {
for (off_t i = 0; vs[i].str; ++i) {
if (vs[i].val == val) {
return i;
}
}
}
return -1;
}
/**
* Generate a statically allocated 'Unknown' string for the provided value.
* The function is not thread-safe (as most of ipmitool).
*
* @param[in] val The value to put into the string
* @returns A pointer to a statically allocated string
*/
static
inline
const char *unknown_val_str(uint32_t val)
{
static char un_str[32];
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%02X)", val);
return un_str;
}
const char * oemval2str(uint32_t oem, uint16_t val,
const struct oemvalstr *vs)
const char *
specific_val2str(uint32_t val,
const struct valstr *specific,
const struct valstr *generic)
{
int i;
if (0 <= (i = find_val_idx(val, specific))) {
return specific[i].str;
}
if (0 <= (i = find_val_idx(val, generic))) {
return generic[i].str;
}
return unknown_val_str(val);
}
const char *val2str(uint32_t val, const struct valstr *vs)
{
return specific_val2str(val, NULL, vs);
}
const char *oemval2str(uint32_t oem, uint32_t val,
const struct oemvalstr *vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].oem != 0xffffff && vs[i].str; i++) {
@ -349,10 +397,7 @@ const char * oemval2str(uint32_t oem, uint16_t val,
}
}
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%X)", val);
return un_str;
return unknown_val_str(val);
}
/* str2double - safely convert string to double
@ -597,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;
@ -1080,3 +1125,35 @@ ipmi_get_oem_id(struct ipmi_intf *intf)
return oem_id;
}
/** Parse command line arguments as numeric byte values (dec or hex)
* and store them in a \p len sized buffer \p out.
*
* @param[in] argc Number of arguments
* @param[in] argv Array of arguments
* @param[out] out The output buffer
* @param[in] len Length of the output buffer in bytes (no null-termination
* is assumed, the input data is treated as raw byte values,
* not as a string.
*
* @returns A success status indicator
* @return false Error
* @return true Success
*/
bool
args2buf(int argc, char *argv[], uint8_t *out, size_t len)
{
size_t i;
for (i = 0; i < len && i < (size_t)argc; ++i) {
uint8_t byte;
if (str2uchar(argv[i], &byte)) {
lprintf(LOG_ERR, "Bad byte value: %s", argv[i]);
return false;
}
out[i] = byte;
}
return true;
}

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) {
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
val2str(ccode, completion_code_vals));
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",

File diff suppressed because it is too large Load Diff

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;
j = i++;
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
j++;
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
if (0 > str2uchar(tok, &rqdata.bytes[count])) {
lprintf(LOG_ERR, "Invalid token in file: [%s]", tok);
rc = -1;
break;
}
tok = strtok(NULL, " ");
++count;
}
if (i < 7) {
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);
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.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:
SDR_ID_TO_CSTRING(desc, record.mcloc);
break;
/* All other records don't have the id_string field */
default:
rc = -1;
break;
}
}
memcpy(buf, desc, __min(sizeof(buf), len));
lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
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,52 +645,63 @@ 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);
IPMI_PASSWORD_SET_PASSWORD, password,
password_type > USER_PW_IPMI15_LEN);
if (eval_ccode(ccode) != 0) {
lprintf(LOG_ERR, "Set User Password command failed (user %d)",
user_id);
user_id);
return (-1);
} else {
printf("Set User Password command successful (user %d)\n",
user_id);
user_id);
return 0;
}
}

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;
}