Inside there will be some C code, some Wireshark dumps and some console commands.
Given: several pieces of hardware that should be polled on the IPMI interface from under GNU / Linux, and two of them that refused to do this.
IPMI (from the English. Intelligent Platform Management Interface) is an intelligent platform management interface designed for offline monitoring and control of functions built directly into the hardware and firmware of server platforms. The key features of IPMI are monitoring, recovery of management functions, logging and inventory, which are available regardless of the processor, BIOS, and operating system. Platform control functions may be available even when the system is in the off state. (Wikipedia)
“Refused to do” - when I tried to connect to them both through the standard ipmitool utility and through my development using the library libOpenIPMI, the connection ended with a timeout error.
It is easy to use. See the SourceForge page for the source code.
(OpenIPMI)
The first solution was found quickly:
ipmitool -I lanplus -H 192.168.14.5 -U ADMIN -P ADMIN mc info
Here, in addition to the standard IPMI connection details, the need to use the RMCP + protocol (included in the IPMI 2.0 specification) is clearly indicated.
')
It would seem that everything should be easy with the OpenIPMI library too.
Though with the documentation of this library, everything is very difficult: a large book is offered as documentation (yes, it is a book in PDF format) called "
A Gentle Introduction to IPMI ". That is, it is impossible to read a short HowTo or Readme, look at the examples and start writing code, periodically looking at the docks for reference, but more is worse: despite the detailed description of the IPMI architecture and library functions, some very basic things are omitted in this manual. For example, how to connect using RMCP +.
Run through the library's header, find what you need in define, and replace it in ipmi_ip_setup_con ()
IPMI_AUTHTYPE_MD5 IPMI_AUTHTYPE_RMCP_PLUS
And here we are waiting for the following problem: the timeout error really disappeared, but the connection function began to produce an error Incorrect argument.
There are no details what this error may mean, neither in the documentation book, nor in the debug messages, anywhere. It is clear that someone (either the library function itself, or a remote device) swears at some argument, but which one, and at what stage the error occurs, is simply impossible to find out. A quick peek at the source suggests that the Incorrect argument (the EINVAL constant) can be returned by different functions in the join process for very different reasons (there are quite a lot of branches and conditions).
Two ways come to mind:
- do a library debug build and examine the debugger step by step what, where and when it happens
- first look at everything that happens from the side, watching the exchange of packets between the client (my application) and the server (piece of hardware) and compare the difference between my implementation and ipmitool, and only then go into the code.
Intuition and the desire for adventure pushed for the second option and were not mistaken.
We start wireshark, we configure the filter and we start to study.

It can be seen that the client and the server exchange request-responses, in the case of working with ipmitool, the exchange continues successfully further, and when using libOpenIPMI everything shuts up.
Question: event incorrect argument occurs somewhere in the bowels of the library, or something does not like the device itself?
Compare the answers from the glands:
(Successful response when using ipmitool)
(Not very successful response when using our application)As you can see, the response from the device is really different - in case of an error, the data block is only 7 bytes in length.
I tried to search the web for a normal description of the RMCP + protocol in order to understand what and how is encoded in this data, but it was to no avail.
The following question arose: what is the difference between the requests sent to the server, that in one case it responds normally, and in the second case something goes wrong?


Looking at the packets being sent, the difference was found, it only remained to find out what these differing bytes meant.
Having rummaged in source codes of function of connection establishment, in send_rmcpp_open_session
The package build algorithm was found:
if ((int) lan->cparm.auth == IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK) data[11] = 0; else { data[11] = 8; data[12] = lan->cparm.auth; } data[16] = 1; if ((int) lan->cparm.integ == IPMI_LANP_INTEGRITY_ALGORITHM_BMCPICK) data[19] = 0; else { data[19] = 8; data[20] = lan->cparm.integ; } data[24] = 2; if ((int) lan->cparm.conf == IPMI_LANP_CONFIDENTIALITY_ALGORITHM_BMCPICK) data[27] = 0; else { data[27] = 8; data[28] = lan->cparm.conf; }
This has already become interesting. Bytes 0x08 in the package clearly caught the eye and said that "this is it here."
In the same place, in the source, there were definees of various authentication options and the like:
#define IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK (~0) #define IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE 0 #define IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1 1 #define IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5 2
From this followed an explicit conclusion that ipmitool initiated a connection with SHA-1 authentication, and for some reason our application with libOpenIPMI tried to connect without protection at all, receiving an ignore response (apparently, the device didn’t like unprotected connections).
Having a little more digging in the source code, it became clear that by default, OpenIPMI chooses the most secure option for establishing a connection, but in our case, according to the library, the most protected option is without any protection.
Further study of the source showed that authentication options are taken from the global auths [] array, where they are added by the ipmi_rmcpp_register_authentication () procedure, but the procedure itself ... where is it called? We search and find:
#ifdef HAVE_OPENSSL ipmi_rmcpp_register_authentication (IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5, NULL); ipmi_rmcpp_register_authentication (IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1, NULL); #endif
that's the answer.
The standard libopenipmi0 package in Ubuntu and Debian is built without the OpenSSL support necessary for these functions. And at least someone would have written the word about this nuance in the documentation!
You can verify this by running
apt-get source libopenipmi0
and looking at the file debian / rules having met there quite a clear line - without-openssl
The solution is to rebuild the package as needed.
sudo apt-get install devscripts build-essential fakeroot sudo apt-get build-dep libopenipmi0 apt-get source libopenipmi0
Install and verify that everything worked as it should.
A little later,
ppa was found, where a kind person recompiles this lib for Ubuntu with support for OpenSSL.
Hooray. Happy end.