Compare commits

...

247 Commits

Author SHA1 Message Date
5d58a9e2e5 This commit was manufactured by cvs2svn to create tag 'IPMITOOL_1_6_1'. 2004-10-08 22:13:10 +00:00
b60c6cea30 update version to 1.6.1 2004-10-08 22:13:09 +00:00
c72e3333eb add Percent Used column to sel info display 2004-10-08 02:52:30 +00:00
ac931daa86 Added a subcommand for testing password (as well as password length per v.2).
Also re-tabified.
2004-10-01 15:24:45 +00:00
3d4acbd829 allow twenty byte passwords 2004-10-01 15:17:48 +00:00
3d790edc6e allow configuring SOL to 9600 bps 2004-09-30 21:37:43 +00:00
4e025b3e0e fix handling of bad SEL entries 2004-09-24 18:21:12 +00:00
62f52f0598 add option to disable libcrypto use for md2/md5 2004-09-20 17:55:51 +00:00
f874a93ccb string compare interface name length fix 2004-09-20 16:41:35 +00:00
1f7ba3dd66 fix intermittant segfault setting lan parameters 2004-09-20 16:40:54 +00:00
e298b0b99f Update name of interface (intf_lanpus ==> lanplus) for check 2004-09-15 15:12:52 +00:00
c84c9dceba change BUF_SIZE to IPMI_BUF_SIZE 2004-09-10 20:19:36 +00:00
7eee9c5916 disable ipmishell on solaris 2004-09-10 20:19:20 +00:00
19fc46049b disable non-solaris interfaces on solaris build 2004-09-10 19:09:17 +00:00
ef11b94155 s/@IPMITOOL_BIN@/@PACKAGE@/g 2004-09-10 19:08:46 +00:00
7ad880076e use strtok instead of strsep because its ANSI-C portable 2004-09-10 18:58:40 +00:00
acc6c80b2d update 2004-09-10 17:09:39 +00:00
517c045873 minor updates 2004-09-10 16:44:40 +00:00
7855f9b4ff install docs in /usr/share/doc/ipmitool
update debian build rules
2004-09-10 04:50:13 +00:00
df2b4c2da1 update to 1.6.0 2004-09-10 04:39:53 +00:00
5e2361ab9c docs are installed automatically 2004-09-10 04:38:07 +00:00
e3e67fbc57 change to 1.6.0 2004-09-10 04:36:20 +00:00
2407e86e90 add README finally 2004-09-10 04:35:45 +00:00
6247d67ec1 add ipmi init script 2004-09-09 23:44:58 +00:00
ed1ee73953 update description 2004-09-08 18:12:17 +00:00
9626375cfb add jeremy to the list 2004-09-03 22:22:03 +00:00
d8b9ae6c8a move shell/exec functions to new file to keep the original
one readable
2004-09-03 22:19:32 +00:00
cb105b246f fix hostname check 2004-09-03 22:18:38 +00:00
4883543139 add configure flag for setting -Wall -Werror status 2004-09-03 22:13:39 +00:00
c8aad7df14 use keepalive when possible to keep sessions open in shell mode,
cleanup 'set' command and have it display message when setting
2004-09-03 19:02:22 +00:00
ba2cfe98a5 add keepalive function for lanplus interface 2004-09-03 19:01:04 +00:00
bdf90c59bc add keepalive function for lan interface 2004-09-03 18:58:59 +00:00
72f6d0b977 two variables for preceeding change 2004-09-02 21:33:51 +00:00
23dc958548 improve the usage help text,
try and workaround SP issues when setting lan parameters
2004-09-02 21:33:17 +00:00
7e140a2c5f add support for "set" command for setting up session variables in shell/exec,
add support for help and up-arrow key in shell mode
2004-09-02 21:32:24 +00:00
4022cb1c63 up debug level for noise 2004-09-02 21:31:04 +00:00
94245169c1 clean up some strval defines that were causing problems with -Wall 2004-09-02 21:30:41 +00:00
3c78114ccc up version to pre5,
fix mis-detectin of libcrypto when testing for md5 presence,
allow --enable-intf-X=static to also work for compatibility reasons
2004-09-02 21:29:03 +00:00
8e7361bb6c fix use of received_byte_count, patch from cyclades 2004-09-02 16:52:33 +00:00
6c43afe6f3 fix a couple missed warnings that gcc 2.95 picked up 2004-09-01 19:27:29 +00:00
e05ab344af use administrator privilege level by default,
add new "exec" command to execute script,
use portable file io
2004-09-01 16:42:59 +00:00
eab79363a2 use portabale file io 2004-09-01 16:41:00 +00:00
c1fd61b419 use portable file io 2004-09-01 16:40:26 +00:00
4763dcf560 fix impi->ipmi typo,
workaround for mBMC
2004-09-01 16:15:24 +00:00
a745d83af2 move file handling routines into helper 2004-09-01 00:19:36 +00:00
6da8379fe4 fix lots of little errors that show up with -Werror -Wall 2004-08-31 23:52:59 +00:00
ea146566c5 clean up handling of top level commands,
add support for "shell" command
2004-08-31 23:15:31 +00:00
bbf1909161 add header interface printing 2004-08-31 23:12:42 +00:00
f6495ddf0e add support for readline,
move raw command to its own file,
remove md5 header that doesn't belong
2004-08-31 23:11:45 +00:00
e092eedd5b fix lots of little errors that show up when compiled with -Wall 2004-08-31 22:55:11 +00:00
8f5e3e0d95 fix segfault on x86_64 by including time.h...
fix lots of little issues that show up when -Wall is turned on
2004-08-31 22:52:54 +00:00
8da3a449cb fix setting Power Restore Policy 2004-08-31 18:48:07 +00:00
639df0246c md2 and md5 were split into here 2004-08-27 19:12:14 +00:00
72417c67db - support for using OpenIPMI MD5 and MD2 implementations if found,
otherwise fall back to internal version
- add "-A authtype" parameter for forcing a certain authtype level
2004-08-27 19:11:43 +00:00
cbc8cbdff4 misc interface opening changes I forgot to propogate 2004-08-27 16:57:04 +00:00
f0cbc9b2ba update to event generation test functions 2004-08-27 16:51:57 +00:00
a8e2fc03e7 a few commands that need to be admin privlege level 2004-08-27 16:51:19 +00:00
4d8ec39062 add new "dump" command to dump the entire sdr to a binary file
relax version check to try and support IPMIv1.0 SDRs
2004-08-27 16:50:14 +00:00
4f9cbb3f38 better handling of fru devices from Tim_T_Murphy@Dell.com
- automatic retries w/ size adjustment when 'get fru info' transfers fail due to size
- support FRU info data formats (4 formats, via type/length byte)
- fix FRU area offset calculation (uchar -> ushort)
- support word-based FRU access as well as byte-based access
- added: 'as-needed' FRU info retrieval
avoids having to retrieve (say) entire 16K, when only a few fields are printed.
~5X response time improvement.
2004-08-27 16:49:20 +00:00
0603bd8f98 export a couple functions for ipmievd,
better handling of description string
2004-08-27 16:47:00 +00:00
69501d7827 minor changes to interface structures 2004-08-27 16:46:06 +00:00
f9c23d8a54 - support for reading/setting BMC Enables
(this code may be trying to be too smart, but it was an interesting test)
2004-08-27 16:45:25 +00:00
6ce168af6f - add new "-f file" param to read lan password from a file
- add new "-t addr" param for bridging to IPMB target
- add new "-m addr" param for setting local IPMB address
- interface loading now has a "default" option
2004-08-27 16:42:50 +00:00
68be9c40e6 now has an option to daemonize and log SEL events to syslog 2004-08-27 16:40:42 +00:00
dd8b1806b5 - remove dynamic interface support
- support for bridged IPMB messages
- add function to build/send IPMI response messages
- fix reporting of "per-msg-auth" and "user-level-auth"
  during Get Channel Authentication Capabilities phase
2004-08-27 16:37:34 +00:00
d92b9920d7 add support for Intel IMB kernel driver (for legacy kernel support)
imbapi.[ch] code is BSD licensed and taken from panicsel.sf.net
2004-08-27 16:33:25 +00:00
45a4c1a9c8 remove dynamic interface support 2004-08-27 16:32:32 +00:00
66aaa91ff2 remove dynamic interface support,
remove my stupid spec-violating pedantic packets
2004-08-27 16:31:53 +00:00
c52b6e80ba update the OpenIPMI interface,
support sending and receiving from IPMB addresses
2004-08-27 16:30:07 +00:00
d5b598c93d all interfaces are static now 2004-08-27 16:29:07 +00:00
c452979e74 add new simple logging functions 2004-08-27 16:27:41 +00:00
81c73bd164 no more ipmiadm so clean the manpage
also get rid of messy bmcautoconf.sh script,
replaced with more flexible bmclanconf
2004-08-27 16:20:29 +00:00
0173930abd no more ltdl 2004-08-27 16:06:39 +00:00
087e8e5a0b build with right arguments when doing dpkg-buildpackage 2004-08-27 16:04:01 +00:00
1ea4e2e540 build system updates for interfaces 2004-08-27 16:01:01 +00:00
b85e953ab9 move rpm specfile,
add hooks for building rpm in arbitrary root
2004-08-27 16:00:20 +00:00
3c61e45ae4 rework configure and build system:
- no more dynamic interfaces
- better handling of openipmi header files
- make rpm commands for building in chroot
2004-08-27 15:59:26 +00:00
2364cd86e8 change email address 2004-08-27 14:33:27 +00:00
7931368837 Adding implementation for "sel get time" and "set set time" 2004-08-25 14:19:46 +00:00
d08d147528 use urandom instead of random 2004-08-13 21:29:40 +00:00
f059085532 add a couple changelog notes for contributed patches 2004-08-06 17:54:35 +00:00
1157a0e498 always initialize pointer to NULL at start of description
function as callers expect it to be initialized but it
isn't always.
2004-08-06 17:50:27 +00:00
2eeceac233 Added user subcommand 2004-08-03 18:40:09 +00:00
7ef44c8a8c adding user subcommand 2004-08-03 18:39:19 +00:00
3f58f3f2aa Added constants for user commands 2004-08-03 18:38:35 +00:00
3fbcd758ca Fixed mispelling 2004-07-30 16:33:25 +00:00
f068a200b6 Added documentation for the lanplus interface 2004-07-30 16:30:20 +00:00
f4a014cac9 Use upper case B for sending breaks 2004-07-30 15:44:55 +00:00
10212fecb5 Added lots of documentation for lanplus and Serial Over LAN commands. 2004-07-30 15:43:31 +00:00
720ad12aaf Store SOL character data input length separately than the data length
of the whole packet.  Turns out we need it in order to determine whether
the BMC only accepted part of our data.
2004-07-29 18:42:22 +00:00
40f77f63a1 Support NACKs 2004-07-29 18:41:23 +00:00
7c9030bf3b Allow update of other SOL parameters 2004-07-29 18:40:52 +00:00
6f1f26a1b1 Increased maximum payload size 2004-07-28 16:05:50 +00:00
5859e5cd57 Added support for callback so that lanplus interface can output data
received while waiting for an ACK.
2004-07-28 15:03:59 +00:00
54c8afcf60 Only send as much data as we are allowed. Added support for
callback so that lanplus library can output data received while
we are waiting for an ACK.
2004-07-28 15:03:06 +00:00
b27ddb4902 SOL plumbing work. Lots of reformatting. 2004-07-28 15:01:57 +00:00
5713ee5fc3 Fixed memory leak. Added assert. 2004-07-28 15:01:00 +00:00
285a4d9ce2 Patch submitted by ebrower at users.sourceforge.net
Add command "bmc info" and related output

Attached is a patch to add an "info" subcommand to the
ipmitool "bmc" command in version 1.5.9. This provides
useful information about the BMC, though I am uncertain
as to the format of the bmc device ID field.
2004-07-26 21:42:09 +00:00
b5c97ace65 Patch submitted by ebrower at users.sourceforge.net
Fix "chassis identify" on some BMCs

On the Intel SE7501WV2 w/ BMC firmware 1.20 it seems
the Chassis Identify command only supports one request
byte (Identify Interval). This patch will cause
requests to use only one byte unless "force" is
specified. The return value of intf->sendrecv() is
also now checked prior to printing an outcome to the
console.

It seems on the Intel SE7501WV2 F/W 1.20 we cannot
assume 2-byte requests will be honored. The BMC
returns CC 0xC7 (Request Data Length Invalid) but this
is not defined within the IPMI 1.5 spec so I assume
other BMC vendors could return other completion codes.
2004-07-26 21:40:32 +00:00
14638f0876 The send_sol interface now returns an impi_rs* 2004-07-23 20:57:06 +00:00
bf5e378272 Incremental changes for SOL. Support for breaks (R. Sunshine). Much
refactoring and cleanup.  More coming soon.
2004-07-23 20:56:17 +00:00
9627ab3253 A bit more error checking 2004-07-21 19:37:43 +00:00
744a151854 Added escape sequences ala ssh. ~. exits. ~^Z suspends, etc. 2004-07-21 19:36:52 +00:00
6174b3b923 Better packet tracking. In fact, great packet tracking. 2004-07-20 22:31:05 +00:00
9a980d55b7 More state for SOL session needed 2004-07-20 22:29:53 +00:00
ca11ec7f52 initialize sol sequence number 2004-07-20 16:19:43 +00:00
fe98eff12f Bump buffer size to 1024 2004-07-20 16:08:25 +00:00
b90b6f0257 Use raw tty mode for SOL session 2004-07-20 16:07:56 +00:00
6801a7300c fix sequence number issues, and abort (for debugging) on error 2004-07-20 16:07:12 +00:00
a3295bba5e print verbose authcode info for -v -v -v -v 2004-07-20 16:05:41 +00:00
c4a390fa77 added interface to send SOL data 2004-07-19 21:02:50 +00:00
c5246ce35d Now sending SOL data to the BMC 2004-07-19 21:02:08 +00:00
e687d531a3 more debug output 2004-07-19 21:01:24 +00:00
de2c6447f0 Now printing data from the BMC 2004-07-19 15:56:59 +00:00
d4edb349a4 made lanplus_crypt_impl a little more verbose 2004-07-19 15:55:35 +00:00
00b6abee9d Incremental changes for SOL. Now receiving (and acking) data from the
BMC.
2004-07-19 15:55:00 +00:00
781d59161e added struct for SOL return data 2004-07-19 15:53:43 +00:00
3d0abad22b Made changes to accomodate SOL 2004-07-19 15:52:46 +00:00
9c24a1efb8 added set-in-progress strings 2004-07-15 15:14:04 +00:00
3aed8f0233 added lots of set parameters 2004-07-15 15:13:45 +00:00
b997633cdc added activate payload return struct 2004-07-15 15:13:03 +00:00
ee4a11550d added SOL session data to the session struct 2004-07-15 15:12:42 +00:00
a33c9103f3 added helpers for the set in progress values 2004-07-15 15:11:37 +00:00
53a67cfc12 reformat help message 2004-07-13 20:32:00 +00:00
e18fb8b260 added documentation for the "sol info" sub-command. 2004-07-12 21:53:57 +00:00
7cd6cfa6e7 Added check for error before printing output 2004-07-12 21:17:49 +00:00
f357316b7f Migrating old sol command to isol 2004-07-12 21:11:38 +00:00
9f72a2203a Migrating old sol setup command to isol. Also, implemented sol configuration
parameter dumping (info command) per the v2.0 specification.
2004-07-12 21:10:21 +00:00
fc176f764a migrating old sol to isol 2004-07-12 21:08:07 +00:00
00e0c7d7fb Use the priv level requested on the command line (default == USER) in the
RAKP1 message
2004-06-16 15:06:33 +00:00
85ed419117 Added support for the GET SDR REPOSITORY INFO command 2004-06-14 20:04:33 +00:00
df13ead528 Added prototypes and structure definitions for the GET SDR REPOSITORY INFO
command.
2004-06-14 20:03:19 +00:00
12d6d12bb7 Added IPMI_GET_SDR_REPOSITORY_INFO 2004-06-14 20:02:26 +00:00
3de1ef09d2 Added information about the SDR info command 2004-06-14 20:01:40 +00:00
3f7c483766 add new bmc configure script 2004-06-11 20:15:17 +00:00
c1b3c9d95a set intf->abort to 0. fixes closing issue. fixed by Wes Bemont. 2004-06-11 19:27:19 +00:00
2d24d4e3fb adjusted error message 2004-06-04 19:47:14 +00:00
db90c6dbdf 1) fix request length bug in session info id subcommand
2) gracefully exit when printing all sessions
3) give useful message for "session info active" requests on session-less
   interfaces
2004-06-04 16:11:54 +00:00
a45fb5e859 store the name of the interface in the interface object 2004-06-04 16:05:22 +00:00
620f9d4aaf allow the interface to store its name 2004-06-04 16:04:37 +00:00
0e9aaceaa7 prettied up the usage 2004-06-04 15:21:59 +00:00
a0b29c3f59 Enhance user command and rename it to getaccess (again).
Implement setaccess command (again).
Remove annoying printbufs in authcap and info.
2004-06-03 16:35:47 +00:00
a5acadbd21 added bswap.h include 2004-06-03 15:28:03 +00:00
d3d78bb7bb added informaton about the session command 2004-06-03 14:39:37 +00:00
c8454885b6 minor changes to close function (copying lan interface close) 2004-06-03 13:57:42 +00:00
4168b3c939 added session command, and modified help output (only -h is used) 2004-06-03 13:56:52 +00:00
6e7b8f1af8 added ipmi_session.c and ipmi_strings.c to build 2004-06-03 13:54:24 +00:00
5dd687134e using ipmi_strings for string values 2004-06-03 13:53:40 +00:00
39167b6ae8 initial checkin 2004-06-03 13:52:55 +00:00
31b25430c1 using ipmi_constants.h for constant definitions 2004-06-03 13:50:59 +00:00
352c2e36ea added ipmi_constants.h ipmi_strings.h and ipmi_session.h to build 2004-06-03 13:50:18 +00:00
6ca108ef78 returning error codes on error 2004-05-28 20:19:13 +00:00
1e043d1188 Fixed many endian-ness problems. Removed commented-out code. 2004-05-27 21:22:19 +00:00
cf563a2e18 added some debug output 2004-05-27 21:17:44 +00:00
4c83f69cae using urandom instead of random 2004-05-27 19:12:26 +00:00
77cf4b9622 fixed some compiler warnings (added string.h include) 2004-05-27 15:55:24 +00:00
61a6e7df12 cleaned up compiler warnings, and fixed some big endian compile errors 2004-05-27 15:54:38 +00:00
873352643a added missing openssl/err.h include 2004-05-27 15:53:52 +00:00
7810d7191b added missing prototype for lanplus_dump_rakp4_message 2004-05-27 15:53:10 +00:00
ac3b1c8eda moved ipmi_csum to helper, as both lan and lanplus use it. 2004-05-27 15:51:35 +00:00
f72472a649 moved ipmi_csum to helper as both lan and lanplus use it. 2004-05-27 15:50:41 +00:00
fd96022ec2 factored ipmi_csum to helper.c, as both lan and lanplus use it. 2004-05-27 15:49:57 +00:00
4a76c7f66c make completion_code_vals extern'd. probably needs to be factored out of
the ipmi_bmc stuff if others are using it.
2004-05-27 14:39:41 +00:00
6b8ebca452 apparently EVP_aes_128_cbc is in libcrypto. 2004-05-27 14:29:42 +00:00
f30ef24600 add support for ipmiv2 with lanplus interface
from Jeremy Ellington
2004-05-25 20:53:51 +00:00
5750269c28 Enhance user command and rename it to getaccess.
Implement setaccess command.
2004-05-11 21:06:47 +00:00
a1f58f6009 Fix call to intf->open to match new definition. 2004-04-26 15:54:34 +00:00
87b893267c don't send ping twice, and don't complain when ping is not answered 2004-04-16 01:00:50 +00:00
a18557d779 fix chassis power control, it needs admin privlvl 2004-04-16 00:14:19 +00:00
0405266402 don't print warning when openipmi header files not found 2004-04-15 20:35:33 +00:00
c96ef9d425 changes to handle session structure inside of intf structure 2004-04-15 20:34:53 +00:00
9ba83a2c5d add note about -L parameter,
changes for "channel info" and "snmp" settings
2004-04-15 20:33:02 +00:00
9b0b5ed676 add ipmi_intf header 2004-04-15 20:29:26 +00:00
ebc1a83c9a add support for setting SNMP community string 2004-04-15 20:27:55 +00:00
c19b71c28c use helper functions to set session variables,
remove "event" and "userinfO" functions from this file
2004-04-15 20:26:53 +00:00
182fd656d2 rework these to open on first call to sendrecv 2004-04-15 20:26:18 +00:00
85e70c1b8d add functions for setting session variables 2004-04-15 20:25:44 +00:00
a1a7a13e56 add support for "channel user" command 2004-04-15 20:25:24 +00:00
68a27c2067 add str2val() and min() helpers 2004-04-15 20:24:35 +00:00
a21bc00e1c rename "Community String" to "SNMP Community String" 2004-04-15 20:23:00 +00:00
f179e04459 move "struct ipmi_intf" and "struct ipmi_session" to ipmi_intf.h 2004-04-15 20:18:29 +00:00
2ab696dc17 add ipmi_event file for event generation 2004-04-15 19:57:05 +00:00
3b58655b89 automatically configure gnu tools for building if on solaris
update pkg tag for building solaris packages
2004-04-12 05:35:50 +00:00
94ea137687 add help for LIPMI interface,
modify install hook to handle DESTDIR variable
2004-04-10 05:05:52 +00:00
ff4e172e8e change help description of solaris driver 2004-04-10 05:04:28 +00:00
cdd1cb6afc don't install header files 2004-04-10 05:03:27 +00:00
99f7f7f61e change references from IPMITOOL_PKG to IPMITOOL_BIN
remove -dev rpm
2004-04-10 05:02:21 +00:00
45e3a3a04a add lipmi plugin support 2004-04-10 05:01:32 +00:00
13c79fa23e add target for building solaris-pkg
add automake option to build bzip2 packages
2004-04-10 05:00:47 +00:00
61f44e20a1 add Solaris package files 2004-04-10 04:59:38 +00:00
db7ce70e24 add lipmi dir 2004-04-10 04:59:14 +00:00
ac328c98bf add interface plugin for Solaris x86 lipmi driver 2004-04-10 04:58:38 +00:00
d0317a2716 build static interfaces by default 2004-04-09 20:47:39 +00:00
bbb7cc35ab remove silly check that prevented setting lan config for channels
other than 6 or 7
2004-04-09 16:45:55 +00:00
7d4b1e8bee remove bmcautoconf.sh from here so its not installed by default
because it doesn't apply to every system
2004-04-09 04:15:41 +00:00
9f055476c3 change variable use from optarg to intfname.. 2004-04-09 04:11:40 +00:00
a7bb4e2ba7 add bmcautoconf to contrib dir since it doesn't apply to all systems 2004-04-09 04:10:37 +00:00
ae3c316bbb fix md5sum generation problem on big-endian,
don't display authcode during session setup
2004-04-02 17:22:53 +00:00
77268f7daa add authtype vals table for lan sessions since the mapping
is not the same as used for authcap
2004-04-02 03:33:47 +00:00
a6793b9430 fix impi -> ipmi typo,
add config.h so WORDS_BIGENDIAN is defined on solaris/sparc
2004-04-02 03:31:06 +00:00
e8170fd6b6 include time.h so strftime doesn't segfault on x86_64 2004-03-31 22:59:11 +00:00
0b3db22dab don't read entire sdr into memory before returning found entry,
instead continue reading where we left of with next call.

add support for getting multiple sensors by name
2004-03-31 18:34:59 +00:00
c7bc504b87 remove ability to find sensor by number,
add support for finding all SDR record types
2004-03-31 17:54:29 +00:00
50b4815cf0 only rename manpage if its necessary 2004-03-31 02:39:37 +00:00
4677f14f6c explicitly list files in debian/ that we want in distribution tarball
because otherwise we get things like CVS/
2004-03-31 02:39:09 +00:00
6e6d775ac8 reflect change to raw command symantics by adding -v to example 2004-03-31 02:38:26 +00:00
44cbf081a6 with raw commands only return the response bytes unless -v is specified 2004-03-31 02:37:14 +00:00
42c1c9123c add COPYING, AUTHORS, ChangeLog to /usr/share/doc 2004-03-27 07:41:51 +00:00
3bf0d0c68e install COPYING, AUTHORS, ChangeLog in /usr/share/doc 2004-03-27 07:41:20 +00:00
99fc2e8a83 only rename manpage if its found 2004-03-27 07:40:59 +00:00
d7af26b64b *** empty log message *** 2004-03-27 07:04:10 +00:00
630be3c669 rearrange so we can use IPMITOOL_BIN in pluginpath variable 2004-03-27 06:56:56 +00:00
6f2eeed320 update changelog for 1.5.9 2004-03-27 06:44:59 +00:00
15b8801d0b pre-process the manpage to change references to the binary name,
add install-data-hook to handle renaming manpage for solaris
2004-03-27 06:40:17 +00:00
d47cd125fe support IPMI_PASSWORD as well 2004-03-27 06:38:47 +00:00
6bc047da44 add privilege level list to channel help 2004-03-27 06:12:18 +00:00
224844746a add channel header 2004-03-27 06:00:16 +00:00
222180ca52 minor change to allow channel field to be "help" 2004-03-27 05:59:33 +00:00
970a87eb1a lost a variable 2004-03-27 05:49:50 +00:00
68556c2a43 add "sensor get|list|thresh" command documentation 2004-03-26 22:06:01 +00:00
c634d2a080 add --enable-ipmiadm configure option to build binary as "ipmiadm"
instead of "ipmitool" to allow Solaris convention of command-line
tools having -adm suffix and GUI tools having -tool suffix.
2004-03-26 21:52:10 +00:00
95044acb5d fix memory leak when interfaces are compiled statically 2004-03-26 21:49:45 +00:00
c199b86143 don't send close session command till after session priviledge level
has been established
2004-03-26 21:43:52 +00:00
e09dc5950c - determine maximum buffer length for SDR reading dynamically
- add support for "sensor get" command
- let sensor get and sensor thresh use sensor id as well as name
- build list of sdrs when searching, for use in xref of sel data
- fix memory leak during sensor list
2004-03-26 21:38:10 +00:00
85d138da01 don't get reservation ID as its not used here 2004-03-26 21:30:23 +00:00
69eeda859e Add options to read password from tty or environment. 2004-03-24 09:27:50 +00:00
05344c9a45 Create the channel command and add authcap subcommand.
Move the chaninfo command to the info subcommand.
from Jeremy Ellington
2004-03-17 22:57:55 +00:00
2a5ea8b9ee Prevent password snooping with ps 2004-03-15 22:10:54 +00:00
a502ab31d1 Fix possible null-pointer references in error handling. 2004-03-10 15:55:33 +00:00
ccf104d610 If we loose the reservation, request a new one and retry the operation. 2004-03-10 15:42:48 +00:00
572f2df8bb repair memory leak on sent packets 2004-03-08 20:31:26 +00:00
9c87f801a4 refine error message when session setup fails 2004-03-04 01:03:22 +00:00
59b1d83751 print message when connection fails 2004-03-03 22:44:15 +00:00
ef055c6246 retry Get Authentication Capabilities command after 1 second pause 2004-03-03 22:26:25 +00:00
0710a0a98e "sel info" : remove 2-space indent, print actual timestamps 2004-03-03 22:25:56 +00:00
706bb54764 increase retrys and introduce pause between attempts,
don't send session close command until session has been
successfully activated
2004-03-03 21:27:30 +00:00
d234596ac5 print message that we are searching for sensor record so
user doesn't think we have stalled
2004-03-03 21:26:00 +00:00
4bfdf06132 don't return NULL for unknown sensor types,
retry on sel reading failure
2004-03-03 21:25:08 +00:00
6e5cdb2c20 use <inttypes.h> instead of <stdint.h> because the latter
does not exist on Solaris 8 and 9
2004-03-03 21:23:20 +00:00
eb116adf53 use <inttypes.h> instead of <stdint.h> becuase the latter doesn't
exist on Solaris 8 and 9
2004-03-03 21:22:32 +00:00
8f48a7021a don't rely on <sys/byteswap.h> having BSWAP_?? define
because it isn't on < Solaris 10
2004-03-03 21:21:21 +00:00
41a64a0f93 fix segfault when password is left blank 2004-02-05 22:06:15 +00:00
1e1058db49 add sensor list, get/set threshold commands 2004-02-05 01:10:25 +00:00
569b8bf5d7 Author: Martin Pool <mbp@sourcefrog.net>
Date: Mon Feb  2 15:07:00 EST 2004

This patch prints ltdl messages when an error occurs, to aid in
debugging.
2004-02-03 01:19:11 +00:00
ceae2f37bf Forgot to mention rrdcgi 2004-02-02 18:02:05 +00:00
1070546b2a Add a README file.
Add an alternative webpage script.
Adjust the graphs a bit.
2004-02-02 17:45:57 +00:00
e0f8bb52bb dynamically allocate fru_data array based on fru.size 2004-02-01 03:17:29 +00:00
101 changed files with 19167 additions and 2033 deletions

View File

@ -1,3 +1,4 @@
Duncan Laurie <duncan@sun.com>
Duncan Laurie <duncan@iceblink.org>
Fredrik <20>hrn <ohrn@chl.chalmers.se>
Jon Cassorla <jon.cassorla@newisys.com>
Jeremy Ellington <jeremy@jeremye.net>

View File

@ -1,3 +1,28 @@
version 1.6.0
* Add a README file
* Add Solaris x86 interface plugin
* Add support for building Solaris packages
* Fix segfault when doing "sel list" (from Matthew Braithwaite)
* Fix "chassis identify" on some BMCs (from ebrower@sourceforge)
* Add command "bmc info" and related output (from ebrower@sourceforge)
* Add support for IPMIv2 and Serial-over-LAN from Jeremy at Newisys
* Add support for building RPMs as non-root user
* Add new "shell" and "exec" commands
* Lots of other contributed patches
version 1.5.9
* Add ability to get a particular sensor by name
* Add ability to set a particular sensor threshold
* Add support for displaying V2 channel authentication levels
* Add README for rrdtool scripts in contrib directory
* Improve lan interface retry handling
* Support prompting for password or reading from environment
* Move chaninfo command into channel subcommand
* Fix reservation ID handling when two sessions open to BMC
* Fix reading of large FRU data
* Add configure option for changing binary to ipmiadm for Solaris
* Fix compile problem on Solaris 8
version 1.5.8
* Enable static compilation of interfaces
* Fix types to be 64-bit safe

View File

@ -32,14 +32,52 @@
# in the design, construction, operation or maintenance of any nuclear
# facility.
EXTRA_DIST = ipmitool.spec.in AUTHORS COPYING ChangeLog debian/*
DOCDIR = $(DESTDIR)/$(datadir)/doc/$(PACKAGE)
DOCLIST = README COPYING AUTHORS ChangeLog
EXTRA_DIST = $(DOCLIST) \
debian/changelog debian/control debian/copyright \
debian/dirs debian/docs debian/rules
AUTOMAKE_OPTIONS = dist-bzip2
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure configure-stamp \
config.guess config.sub depcomp install-sh ltmain.sh missing \
mkinstalldirs config.h.in stamp-h.in $(distdir).tar.gz
mkinstalldirs config.h.in stamp-h.in \
$(distdir).tar.gz $(distdir).tar.bz2
SUBDIRS = libltdl lib src include doc contrib
SUBDIRS = lib src include doc contrib control
dist-hook: ipmitool.spec
cp ipmitool.spec $(distdir)
dist-hook:
cp control/ipmitool.spec $(distdir)
install-data-local:
mkdir -p $(DOCDIR)
install -m 644 $(DOCLIST) $(DOCDIR)
.PHONY: pkg
pkg: PKG := ipmitool-@VERSION@-@OS@-@ARCH@
pkg: control/pkginfo
$(STRIP) src/ipmitool
$(STRIP) src/ipmitool
(cd control ; pkgmk -o -d /tmp)
pkgtrans -s /tmp $(PKG) ipmitool
gzip -c /tmp/$(PKG) > $(PKG).gz
-rm -rf /tmp/ipmitool /tmp/$(PKG)
BUILDDIR = ${shell cd $(top_builddir) ; pwd | sed -e 's,^[^:\\/]:[\\/],/,'}
SRCDIR = ${shell cd $(top_srcdir) ; pwd | sed -e 's,^[^:\\/]:[\\/],/,'}
RPMDIR = $(BUILDDIR)/rpmbuild
.PHONY: rpm
rpm: control/ipmitool.spec dist
mkdir -p $(RPMDIR)/{BUILD,RPMS,SRPMS,SOURCES,SPECS,tmp}
cp control/ipmitool.spec $(RPMDIR)/SPECS
BUILDDIR=$(RPMDIR) CONFIGDIR=$(BUILDDIR)/control \
@RPMBUILD@ -ba --rcfile $(SRCDIR)/control/rpmrc \
$(RPMDIR)/SPECS/ipmitool.spec
.PHONY: clean-rpm
clean-rpm:
-rm -rf $(RPMDIR)

310
ipmitool/README Normal file
View File

@ -0,0 +1,310 @@
ipmitool
Duncan Laurie
duncan@iceblink.org
Overview
========
ipmitool is a utility for managing and configuring devices that support
the Intelligent Platform Management Interface. IPMI is an open standard
for monitoring, logging, recovery, inventory, and control of hardware
that is implemented independent of the main CPU, BIOS, and OS. The
service processor (or Baseboard Management Controller, BMC) is the brain
behind platform management and its primary purpose is to handle the
autonomous sensor monitoring and event logging features.
The ipmitool program provides a simple command-line interface to this BMC.
It features the ability to read the sensor data repository (SDR) and print
sensor values, display the contents of the System Event Log (SEL), print
Field Replaceable Unit (FRU) inventory information, read and set LAN
configuration parameters, and perform remote chassis power control.
Background
==========
I originally wrote ipmitool while between projects and employeed at Sun
Microsystems. Sun had just embarked on a new line of general-purpose x86
servers that inclued an OEM Intel board with an IPMIv1.5 BMC on board.
It started with an idea that remote chassis power control would be a handy
feature for my systems in the lab and from there it grew into a multi-
purpose tool that lots of people found useful. I decided to release it
under a BSD license and give others the chance to make use of it.
ipmitool was not written to provide large-scale (aka Enterprise) management
application functionality. The functionality that ipmitool proivides is
easily accomplished by sending simple IPMI request messages and parsing
the returned response. It is intended to be used by system administrators
who like the simplicity and scriptability of command-line utilities, as
well as those debugging or developing their own BMC implementations.
Requirements
============
Obviously the largest requirement is hardware with a service processor
that supports the IPMI specification. Many x86-based servers are now
comming with IPMI support, check with your preferred hardware vendor
about available prodcuts.
Once you are certain you have the required hardware, you then need to
decide how you want to access the BMC. The most common case involve
access through the System Interface or over the LAN. (or serial, but
currently ipmitool does not support the serial interface)
System Interface
----------------
There are multiple types of system interfaces, but they are all similar
enough to allow a single well-designed driver to support them all.
Different types of system interfaces include Keyboard Controller Style
(KCS), Block Transfer (BT), System Management Interface Chip (SMIC) and
SMBus. Different hardware vendors will have different preference and
implementations.
On Linux the OpenIPMI kernel driver should support all of these system
interfaces and it should be a simple matter of loading the right
kernel modules and setting up the device node to use it. The driver
module names vary slightly in different kernel versions, but for all
releases you need these two modules:
ipmi_msghandler: incoming and outgoing message handler
ipmi_devintf: character device interface to IPMI driver
For 2.4.x and early 2.6.x kernels you need to choose a module based on
the type of system interface your hardware supports. For example:
ipmi_kcs_drv: Keyboard Controller Style driver
More recent 2.6.x kernels have combined these into a single module:
ipmi_si: a universal IPMI system interface driver
See the documentation that comes with your distribution and/or kernel
for more information on what kernel modules are required. Once the
required modules are loaded and the driver has found a suitable system
interface to the BMC then you need to ensure the device node at
/dev/ipmi0 is pointing at the correct major number.
This is because OpenIPMI is given a dynamically assigned major number
when it is loaded, but depending on what other modules are present
this number may be anywhere from 254 on down. The easiest way to tell
is to check the output of /proc/devices and see what major number the
"ipmidev" device is assigned to.
There is a sample script included with ipmitool called ipmi.init that
can be used to automate this process at bootup.
LAN Interface
-------------
This is often referred to as "IPMI-over-LAN" and defines how IPMI messages
can be sent to and from the BMC encapsulated in Remote Management Control
Protocol (RMCP) packets which are then transferred as UDP datagrams.
IPMI-over-LAN is only supported with version 1.5 and higher of the IPMI
specification. The RMCP packet format is defined by the Alert Standard
Forum, and it has been followed up with the RMCP+ protocol that adds
encryption and payload support. The IPMIv2 specification was updated
accordingly to to support the RMCP+ protocol and brings with it enhanced
security with encryption as well as support for Serial over LAN.
There are different types of LAN interfaces as well. Some systems have
shared management networks where the NIC will intercept UDP packets to
port 623 and redirect them to the BMC over SMBUS. This type of LAN
interface requires that the BMC be configured with the same settings that
the system uses. It also suffers from an increased security risk just by
the nature of sharing that interface with normal traffic.
I have also seen bugs in some implementations that have rendered the
IPMI-over-LAN feature "dangerous" to enable in some situations. (in
particular there can be an issue with RPC because it will sometimes choose
to use port 623 and you will lose response packets...)
There is a sample shell script included with ipmitool called bmclanconf
that can be used to simplify the LAN settings configuration process using
the System Interface to configure the settings. In some cases the
hardware will come with a utility (often a DOS bootable CD) for configuring
enabling the LAN interface as well.
In order to support the IPMIv2.0 interface you must have an OpenSSL library
with the required encrytion functions. Recent distributions should have
no problems. The IPMIv1.5 interface will attempt to use OpenSSL for MD5
hash function at compile time but if that is not found it will use an
internal library.
Usage
=====
All invocations of ipmitool require specifying an interface to use, unless
you want to use the default interface as set at compile time. Each call
must also specify a command to run. You can see the list of supported
interfaces and which is default as well as a list of top level commands in
the usage output available with the -h option:
usage: ipmitool [options...] <command>
-h This help
-V Show version information
-v Verbose (can use multiple times)
-c Display output in comma separated format
-I intf Interface to use
-H hostname Remote host name for LAN interface
-p port Remote RMCP port [default=623]
-L level Remote session privilege level [default=USER]
-A authtype Force use of authtype NONE, PASSWORD, MD2 or MD5
-U username Remote session username
-P password Remote session password
-f file Read remote session password from file
-a Prompt for remote password
-E Read password from IPMI_PASSWORD environment variable
-m address Set local IPMB address
-t address Bridge request to remote target address
Interfaces:
open Linux OpenIPMI Interface [default]
imb Intel IMB Interface
lan IPMI v1.5 LAN Interface
lanplus IPMI v2.0 RMCP+ LAN Interface
Commands:
raw Send a RAW IPMI request and print response
lan Configure LAN Channels
chassis Get chassis status and set power state
event Send pre-defined events to BMC
bmc Print BMC status and configure global enables
sdr Print Sensor Data Repository entries and readings
sensor Print detailed sensor information
fru Print built-in FRU and scan SDR for FRU locators
sel Print System Evelnt Log
sol Configure IPMIv2.0 Serial-over-LAN
isol Configure Intel IPMIv1.5 Serial-over-LAN
user Configure BMC users
channel Configure BMC channels
session Print session information
shell Launch interactive IPMI shell
exec Run list of commands from file
set Set runtime variable for shell and exec
Commands
========
More help on the supported commands can be found by running them with the
help argument, for example "chassis help". There are a few commands with
special meaning:
> shell: This command will launch an shell interface to the ipmitool
command set. You can use this for interactively entering commands to
monitor system status. An example session:
# ipmitool -I open shell
ipmitool> chassis status
System Power : off
Power Overload : false
Power Interlock : inactive
Main Power Fault : false
Power Control Fault : false
Power Restore Policy : always-off
Last Power Event : command
Chassis Intrusion : active
Front-Panel Lockout : inactive
Drive Fault : false
Cooling/Fan Fault : false
ipmitool> user list 7
ID Name Callin Link Auth IPMI Msg Channel Priv Limit
1 true false true ADMINISTRATOR
ipmitool> exit
> exec: This command will read a text file and execute ipmitool commands
in sequence. It can be used for scriptable commands:
# cat lansetup.scr
lan set 7 ipsrc static
lan set 7 ipaddr 10.1.1.10
lan set 7 netmask 255.255.255.0
lan set 7 defgw ipaddr 10.1.1.254
# ipmitool -I open exec lansetup.scr
Setting LAN IP Address to 10.1.1.10
Setting Lan Subnet Mask to 255.255.255.0
Setting Lan Default Gateway IP to 10.1.1.254
> set: This command can be used by the shell and exec modes to configure
various session parameters:
hostname <host> Session hostname
username <user> Session username
password <pass> Session password
privlvl <level> Session privilege level force
authtype <type> Authentication type force
localaddr <addr> Local IPMB address
targetaddr <addr> Remote target IPMB address
port <port> Remote RMCP port
csv [level] enable output in comma separated format
verbose [level] Verbose level
# cat getstatus.scr
set hostname sf-v20z-1
set password admin
chassis status
# ipmitool -I lan exec getstatus.scr
Set session hostname to lx50
Set session password
System Power : off
Power Overload : false
Power Interlock : inactive
Main Power Fault : false
Power Control Fault : false
Power Restore Policy : always-off
Last Power Event : command
Chassis Intrusion : active
Front-Panel Lockout : inactive
Drive Fault : false
Cooling/Fan Fault : false
ipmievd
=======
Included with ipmitool is another utility called ipmievd that is a daemon
which will listen for events from the BMC that are being sent to the SEL
and also log those messages to syslog. By default when run (as root) with
no arguments it will daemonize and poll on the OpenIPMI device waiting for
an event notification. Upon receipt of an event it will log it to syslog
with the LOG_LOCAL4 facility. You can test ipmievd by sending test events
over the LAN interface with ipmitool:
remote# ipmievd
local$ ipmitool -I lan -H lx50 -P admin event help
usage: event <num>
1 : Temperature - Upper Critical - Going High
2 : Voltage Threshold - Lower Critical - Going Low
3 : Memory - Correctable ECC
local$ ipmitool -I lan -H lx50 -P admin event 1
Sending Temperature - Upper Critical - Going High event to BMC
local$ ipmitool -I lan -H lx50 -P admin event 2
Sending Voltage Threshold - Lower Critical - Going Low event to BMC
local$ ipmitool -I lan -H lx50 -P admin event 3
Sending Memory - Correctable ECC event to BMC
remote# tail /var/log/messages (timestamps removed)
ipmievd: Waiting for events...
ipmievd: Temperature Sensor 30 - Upper Critical - going high
ipmievd: Voltage Sensor 60 - Lower Critical - going low
ipmievd: Memory Sensor 01 - Correctable ECC
Resources
=========
IPMItool homepage
http://ipmitool.sourceforge.net
IPMItool manpage
http://ipmitool.sourceforge.net/manpage.html
IPMItool overview paper from Linux.conf.au 2004
http://ipmitool.sourceforge.net/lca2004_ipmitool.pdf
Intelligent Platform Management Interface specification
http://www.intel.com/design/servers/ipmi/spec.htm
OpenIPMI project: Linux IPMI kernel driver and userland library
http://openipmi.sourceforge.net

View File

@ -35,7 +35,7 @@
# facility.
aclocal
libtoolize --automake --copy --ltdl
libtoolize --automake --copy
autoheader
automake --foreign --add-missing --copy

View File

@ -2,70 +2,46 @@ dnl
dnl autoconf for ipmitool
dnl
AC_INIT([src/ipmitool.c])
AM_INIT_AUTOMAKE([ipmitool], [1.5.9])
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE([ipmitool], [1.6.1])
AM_CONFIG_HEADER(config.h)
AC_CONFIG_SRCDIR([src/ipmitool.c])
AC_PREREQ(2.50)
IPMITOOL_PKG=ipmitool
AC_SUBST(IPMITOOL_PKG)
AC_SUBST(ac_configure_args)
dnl check for programs
dnl check for requirements
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_CHECK_PROG([RPMBUILD], [rpmbuild], [rpmbuild], [rpm])
AC_CHECK_PROG([SED], [sed], [sed])
AC_CHECK_PROG(SED, sed, sed)
dnl setup libtool
AC_LIB_LTDL
AC_LIBTOOL_DLOPEN
AC_LIBLTDL_CONVENIENCE
AM_PROG_LIBTOOL
LIBTOOL="$LIBTOOL --silent"
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
AC_CONFIG_SUBDIRS(libltdl)
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(socket, socket, ,
[AC_CHECK_LIB(nsl, socket, LIBS="$LIBS -lsocket -lnsl", , -lsocket)])
dnl check for headers
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h string.h sys/ioctl.h sys/stat.h unistd.h])
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h sys/socket.h])
AC_CHECK_HEADERS([sys/byteorder.h byteswap.h])
dnl check for typedefs, structs, and compiler options
AC_C_CONST
AC_C_INLINE
AC_C_BIGENDIAN
dnl check for lib functions
AC_FUNC_MALLOC
AC_FUNC_SELECT_ARGTYPES
AC_FUNC_STAT
AC_FUNC_STRTOD
AC_CHECK_FUNCS([alarm gethostbyname socket select])
AC_CHECK_FUNCS([memmove memset strchr strdup strerror])
AC_CHECK_FUNCS([getpassphrase])
dnl check for byteswap functionality
AC_CHECK_HEADERS([sys/byteorder.h byteswap.h])
CFLAGS="$CFLAGS -fno-strict-aliasing"
dnl set kernel directory for openipmi header files
AC_ARG_WITH([kerneldir],
[[ --with-kerneldir=DIR Set kernel path to DIR]],
[kerneldir="$withval"],
[kerneldir="/usr/src/linux-2.4"])
CFLAGS="$CFLAGS -I${kerneldir}/include"
AC_SUBST(CFLAGS)
AM_PROG_LIBTOOL
LIBTOOL="$LIBTOOL --silent"
have_openipmi=no
AC_CHECK_HEADER([linux/ipmi.h],
[have_openipmi=yes],
[AC_MSG_WARN([Unable to find OpenIPMI header files])])
AC_SEARCH_LIBS([gethostbyname], [nsl])
AC_SEARCH_LIBS([socket], [socket], [],
[AC_CHECK_LIB([nsl], [socket],
[LIBS="$LIBS -lsocket -lnsl"], [], [-lsocket])])
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
@ -75,103 +51,231 @@ if test "x$exec_prefix" = "xNONE"; then
exec_prefix="$prefix"
fi
dnl enable plugins for interfaces
AC_ARG_WITH([plugin-path],
[[ --with-plugin-path=DIR Set plugin path to DIR]],
[pluginpath="$withval"],
[pluginpath="${exec_prefix}/lib/ipmitool"])
dnl set some things so we build with GNU tools on Solaris
case "$host_os" in
solaris*)
MAKE=gmake
STRIP=gstrip
LD=gld
AR=gar
# disable the linux-specific interfaces
enable_intf_imb=no
enable_intf_open=no
enable_ipmievd=no
enable_ipmishell=no
;;
esac
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$pluginpath", "IPMI interface plugin path")
AC_SUBST(pluginpath)
AC_SUBST(ARCH, $host_cpu)
AC_SUBST(OS, $host_os)
AC_SUBST(PSTAMP, $host)
AC_SUBST(BASEDIR, $prefix)
STATIC_INTF_LIST=
STATIC_INTF=
STATIC_INTF_EXT=
STATIC_INTF_LIB=
dnl check for OpenSSL functionality
AC_ARG_ENABLE([internal-md5],
[AC_HELP_STRING([--enable-internal-md5],
[enable internal MD5 library [default=no]])],
[], [enable_internal_md5=no])
PLUGIN_INTF_LAN=
STATIC_INTF_LAN=
LDFLAGS_INTF_LAN=
AC_ARG_ENABLE([intf-lan],
[[ --enable-intf-lan enable IPMI-over-LAN interface [default=yes]]],
[if test "x$enableval" = "xyes"; then
AC_SUBST(INTF_LAN,lan)
PLUGIN_INTF_LAN="libintf_lan.la"
LDFLAGS_INTF_LAN="-rpath $pluginpath -avoid-version"
DYNAMIC_INTF_LIST="lan $DYNAMIC_INTF_LIST"
elif test "x$enableval" = "xstatic"; then
AC_SUBST(INTF_LAN,lan)
STATIC_INTF_LAN="libintf_lan.la"
STATIC_INTF_LIST="lan $STATIC_INTF_LIST"
fi],
[AC_SUBST(INTF_LAN,lan)
PLUGIN_INTF_LAN="libintf_lan.la"
LDFLAGS_INTF_LAN="-rpath $pluginpath -avoid-version"
DYNAMIC_INTF_LIST="lan $DYNAMIC_INTF_LIST"
])
AC_SUBST(PLUGIN_INTF_LAN)
AC_SUBST(STATIC_INTF_LAN)
AC_SUBST(LDFLAGS_INTF_LAN)
AC_CHECK_LIB([crypto], [EVP_aes_128_cbc],
[if test "x$enable_internal_md5" != "xyes"; then
have_crypto=yes; LIBS="$LIBS -lcrypto"
fi], [have_crypto=no], [-lcrypto])
PLUGIN_INTF_OPEN=
STATIC_INTF_OPEN=
LDFLAGS_INTF_OPEN=
AC_ARG_ENABLE([intf-open],
[[ --enable-intf-open enable OpenIPMI device interface [default=no]]],
[if test "x$enableval" = "xyes"; then
if test "x$have_openipmi" = "xyes"; then
AC_SUBST(INTF_OPEN,open)
PLUGIN_INTF_OPEN="libintf_open.la"
LDFLAGS_INTF_OPEN="-rpath $pluginpath -avoid-version"
DYNAMIC_INTF_LIST="open $DYNAMIC_INTF_LIST"
else
echo "** Unable to build OpenIPMI interface support!"
exit 1
AC_CHECK_LIB([crypto], [MD5_Init],
[if test "x$enable_internal_md5" != "xyes"; then
if test "x$have_crypto" != "xyes"; then
LIBS="$LIBS -lcrypto"
have_md5=yes
fi
AC_DEFINE(HAVE_CRYPTO_MD5, [1], [Define to 1 if libcrypto supports MD5.])
fi], [], [-lcrypto])
AC_CHECK_LIB([crypto], [MD2_Init],
[if test "x$enable_internal_md5" != "xyes"; then
if test "x$have_crypto" != "xyes" && test "x$have_md5" != "xyes"; then
LIBS="$LIBS -lcrypto"
have_md2=yes
fi
AC_DEFINE(HAVE_CRYPTO_MD2, [1], [Define to 1 if libcrypto supports MD2.])
fi], [], [-lcrypto])
dnl enable IPMIv1.5 LAN interface
AC_ARG_ENABLE([intf-lan],
[AC_HELP_STRING([--enable-intf-lan],
[enable IPMIv1.5 LAN interface [default=yes]])],
[], [enable_intf_lan=yes])
if test "x$enable_intf_lan" = "xstatic" || test "x$enable_intf_lan" = "xplugin"; then
enable_intf_lan=yes
fi
if test "x$enable_intf_lan" = "xyes"; then
AC_DEFINE(IPMI_INTF_LAN, [1], [Define to 1 to enable LAN IPMIv1.5 interface.])
AC_SUBST(INTF_LAN, [lan])
AC_SUBST(INTF_LAN_LIB, [libintf_lan.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la"
fi
dnl enable IPMIv2.0 RMCP+ LAN interface
AC_ARG_ENABLE([intf-lanplus],
[AC_HELP_STRING([--enable-intf-lanplus],
[enable IPMIv2.0 RMCP+ LAN interface [default=auto]])],
[if test "x$enable_intf_lanplus" != "xno" && test "x$have_crypto" != "xyes"; then
echo "** The lanplus interface requires an SSL library with EVP_aes_128_cbc defined."
enable_intf_lanplus=no
fi],
[enable_intf_lanplus=$have_crypto])
if test "x$enable_intf_lanplus" = "xstatic" || test "x$enable_intf_lanplus" = "xplugin"; then
enable_intf_lanplus=yes
fi
if test "x$enable_intf_lanplus" = "xyes"; then
AC_DEFINE(IPMI_INTF_LANPLUS, [1], [Define to 1 to enable LAN+ IPMIv2 interface.])
AC_SUBST(INTF_LANPLUS, [lanplus])
AC_SUBST(INTF_LANPLUS_LIB, [libintf_lanplus.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lanplus/libintf_lanplus.la"
else
enable_intf_lanplus=no
fi
dnl look for OpenIPMI header files
AC_ARG_WITH([kerneldir],
[AC_HELP_STRING([--with-kerneldir=DIR],
[set kernel include path to DIR])],
[if test "x$with_kerneldir" = "xyes"; then
with_kerneldir="/lib/modules/`uname -r`/build"
fi
CFLAGS="$CFLAGS -I ${with_kerneldir}/include"
AC_SUBST(CFLAGS)
if test -s ${with_kerneldir}/include/linux/version.h ; then
kernelver=`grep UTS_RELEASE ${with_kerneldir}/include/linux/version.h | \
sed 's/^\#define UTS_RELEASE \"\(2\.[0-9]\)\..*/\1/'`
if test "x$kernelver" = "x2.6"; then
CPPFLAGS="$CPPFLAGS -D__user="
AC_SUBST(CPPFLAGS)
fi
elif test "x$enableval" = "xstatic"; then
AC_SUBST(INTF_OPEN,open)
STATIC_INTF_OPEN="libintf_open.la"
STATIC_INTF_LIST="open $STATIC_INTF_LIST"
fi])
AC_SUBST(PLUGIN_INTF_OPEN)
AC_SUBST(STATIC_INTF_OPEN)
AC_SUBST(LDFLAGS_INTF_OPEN)
AC_CHECK_HEADER([linux/ipmi.h],
[AC_DEFINE(HAVE_OPENIPMI_H, [1],
[Define to 1 if you have the <linux/ipmi.h> header file.])],
[echo "** Unable to find OpenIPMI header files. Using internal version."])
for name in $STATIC_INTF_LIST; do
STATIC_INTF="$STATIC_INTF { \"intf_${name}\", ${name}_intf_setup },";
STATIC_INTF_EXT="$STATIC_INTF_EXT extern int ${name}_intf_setup(struct ipmi_intf ** intf);";
STATIC_INTF_LIB="$STATIC_INTF_LIB \$(top_builddir)/src/plugins/${name}/libintf_${name}.la";
done
dnl enable Linux OpenIPMI interface
AC_ARG_ENABLE([intf-open],
[AC_HELP_STRING([--enable-intf-open],
[enable Linux OpenIPMI interface [default=yes]])],
[], [enable_intf_open=yes])
if test "x$enable_intf_open" = "xstatic" || test "x$enable_intf_open" = "xplugin"; then
enable_intf_open=yes
fi
if test "x$enable_intf_open" = "xyes"; then
AC_DEFINE(IPMI_INTF_OPEN, [1], [Define to 1 to enable Linux OpenIPMI interface.])
AC_SUBST(INTF_OPEN, [open])
AC_SUBST(INTF_OPEN_LIB, [libintf_open.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB open/libintf_open.la"
fi
AC_SUBST(STATIC_INTF)
AC_SUBST(STATIC_INTF_EXT)
AC_SUBST(STATIC_INTF_LIB)
dnl enable Intel IMB interface
AC_ARG_ENABLE([intf-imb],
[AC_HELP_STRING([--enable-intf-imb],
[enable Intel IMB driver interface [default=yes]])],
[], [enable_intf_imb=yes])
if test "x$enable_intf_imb" = "xstatic" || test "x$enable_intf_imb" = "xplugin"; then
enable_intf_imb=yes
fi
if test "x$enable_intf_imb" = "xyes"; then
AC_DEFINE(IPMI_INTF_IMB, [1], [Define to 1 to enable Intel IMB interface.])
AC_SUBST(INTF_IMB, [imb])
AC_SUBST(INTF_IMB_LIB, [libintf_imb.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB imb/libintf_imb.la"
fi
dnl enable Solaris LIPMI interface
AC_CHECK_HEADER([sys/lipmi/lipmi_intf.h], [have_lipmi=yes], [have_lipmi=no])
AC_ARG_ENABLE([intf-lipmi],
[AC_HELP_STRING([--enable-intf-lipmi],
[enable Solaris x86 IPMI interface [default=auto]])],
[if test "x$enable_intf_lipmi" != "xno" && test "x$have_lipmi" != "xyes"; then
echo "** Unable to build Solaris x86 IPMI interface support!"
enable_intf_lipmi=no
fi],
[enable_intf_lipmi=$have_lipmi])
if test "x$enable_intf_lipmi" = "xstatic" || test "x$enable_intf_lipmi" = "xplugin"; then
enable_intf_lipmi=yes
fi
if test "x$enable_intf_lipmi" = "xyes"; then
AC_DEFINE(IPMI_INTF_LIPMI, [1], [Define to 1 to enable Solaris LIPMI interface.])
AC_SUBST(INTF_LIPMI, [lipmi])
AC_SUBST(INTF_LIPMI_LIB, [libintf_lipmi.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lipmi/libintf_lipmi.la"
fi
AC_SUBST(IPMITOOL_INTF_LIB)
dnl check for readline library to enable ipmi shell
have_readline=no
AC_SEARCH_LIBS([readline], [readline], [have_readline=yes],
[AC_CHECK_LIB([readline], [readline],
[have_readline=yes], [], [-lcurses])])
AC_ARG_ENABLE([ipmishell],
[AC_HELP_STRING([--enable-ipmishell],
[enable IPMI shell interface [default=yes]])],
[], [enable_ipmishell=yes])
if test "x$enable_ipmishell" = "xyes" && test "x$have_readline" = "xyes"; then
AC_DEFINE(HAVE_READLINE, [1], [Define to 1 if readline present.])
LIBS="$LIBS -lcurses -lreadline"
fi
dnl enable IPMI Event Daemon
AC_ARG_ENABLE([ipmievd],
[[ --enable-ipmievd enable IPMI event daemon [default=no]]],,enable_ipmievd=no)
AM_CONDITIONAL(IPMIEVD, test "x$enable_ipmievd" = "xyes")
[AC_HELP_STRING([--enable-ipmievd],
[enable IPMI Event daemon [default=yes]])],
[], [enable_ipmievd=yes])
AM_CONDITIONAL(IPMIEVD, [test "x$enable_ipmievd" = "xyes"])
if test "x$enable_ipmievd" = "xyes"; then
AC_SUBST(IPMIEVD_BIN, [ipmievd])
fi
AC_CONFIG_FILES([ipmitool.spec
Makefile
dnl Enable -Wall -Werror
AC_ARG_ENABLE([buildcheck],
[AC_HELP_STRING([--enable-buildcheck],
[enable -Wall -Werror for build testing [default=no]])],
[if test "x$enable_buildcheck" != "xno"; then
CFLAGS="$CFLAGS -Wall -Werror"
fi], [])
AC_SUBST(CFLAGS)
dnl Generate files for build
AC_CONFIG_FILES([Makefile
doc/Makefile
contrib/Makefile
control/Makefile
control/pkginfo
control/prototype
control/ipmitool.spec
lib/Makefile
include/Makefile
include/ipmitool/Makefile
src/Makefile
src/plugins/ipmi_intf_static.c
src/plugins/Makefile
src/plugins/lan/Makefile
src/plugins/open/Makefile])
src/plugins/lanplus/Makefile
src/plugins/open/Makefile
src/plugins/imb/Makefile
src/plugins/lipmi/Makefile])
AC_OUTPUT
AC_MSG_RESULT([])
AC_MSG_RESULT([$PACKAGE $VERSION])
AC_MSG_RESULT([ipmitool $VERSION])
AC_MSG_RESULT([])
AC_MSG_RESULT([ Interface Path........ : $pluginpath])
AC_MSG_RESULT([ Static Interfaces..... : $STATIC_INTF_LIST])
AC_MSG_RESULT([ Dynamic Interfaces.... : $DYNAMIC_INTF_LIST])
AC_MSG_RESULT([ Build ipmievd......... : $enable_ipmievd])
AC_MSG_RESULT([Interfaces])
AC_MSG_RESULT([ lan : $enable_intf_lan])
AC_MSG_RESULT([ lanplus : $enable_intf_lanplus])
AC_MSG_RESULT([ open : $enable_intf_open])
AC_MSG_RESULT([ imb : $enable_intf_imb])
AC_MSG_RESULT([ lipmi : $enable_intf_lipmi])
AC_MSG_RESULT([])
AC_MSG_RESULT([Extra tools])
AC_MSG_RESULT([ ipmievd : $enable_ipmievd])
AC_MSG_RESULT([])

View File

@ -34,5 +34,6 @@
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = collect_data.sh create_rrds.sh create_webpage.sh
dist_pkgdata_DATA = bmclanconf ipmi.init README \
collect_data.sh create_rrds.sh create_webpage_compact.sh create_webpage.sh

95
ipmitool/contrib/README Normal file
View File

@ -0,0 +1,95 @@
Graphs for ipmitool
-------------------
This is a set of shell-scripts to quickly create a webpage with pretty graphs!
Prerequisites are a webserver with cgi-bin support and RRDtool, a data
collection and graphing utility you can get here:
http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/
First, decide on a directory where to store the RRDtool database files and make
sure it exists. The user that will run the cronjob to collect updates must have
write permissions in this dir.
Next, you'll need to edit some variables at the top of each script.
Common to all scripts:
hostname Override this if you are collecting data from a remote host,
or if the $HOSTNAME variable is incorrect.
ipmi_cmd Command line used to call ipmitool. Default is to collect
data from the local server using OpenIPMI.
If you want to collect data from a remote host, add the
-I lan, -H, -U and -P options as necessary.
BIG NOTE! I do not recommend using remote data collection since
you'll have to store the password in the script. If you do,
make sure unauthorized people can't read or execute the scripts
or they'll be able to wreak havoc on your server.
rrd_dir Enter the dir where to store the RRDtool database here.
Now you can get the data collection going. Run create_rrds.sh to create the
RDDtool database, you'll find one .rrd file per sensor in the designated dir.
Add a line to your crontab that executes collect_data.sh every 5 minutes.
Something like this:
*/5 * * * * /usr/local/bin/collect_data.sh
If you are a Solaris user you'll have to write the more verbose:
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/local/bin/collect_data.sh
Finally it's time to create the webpage, begin with editing some more variables
in the create_webpage.sh and/or create_webpage_compact.sh scripts:
rrdcgi Full path to the rrdcgi executable.
img_dir Directory to store the graph images. This path must be within
the document root and writable by the web server user.
Example: /usr/local/apache2/htdocs/images/graphs
web_dir Relative path of the URL where the images will show up
on the web server.
Example: With the img_dir path above the corresponding web_dir
would be /images/graphs
graph_width Size of the graph area in pixels (excluding title, legends etc.)
graph_height
graph_daily Decide which of daily, weekly and monthly graphs you want
graph_weekly included on the page.
graph_monthly
Finally run the create webpage script and store the output as a cgi-script and
don't forget to make it executable.
Example:
create_webpage.sh > /usr/local/apache2/cgi-bin/my_ipmi_graphs.cgi
chmod 755 /usr/local/apache2/cgi-bin/my_ipmi_graphs.cgi
Now you can surf to http://my.server.com/cgi-bin/my_ipmi_graphs.cgi and enjoy!
The difference between create_webpage.sh and create_webpage_compact.sh is that
the first script displays sensor thresholds in the graphs. The second script
collects all sensors that measure the same unit into the same graph thus
producing a lot fewer graphs.
Note, RRDtool sometimes scales the graphs such that the sensor thresholds
fall outside the visible area.
Happy graphing!

313
ipmitool/contrib/bmclanconf Executable file
View File

@ -0,0 +1,313 @@
#!/bin/bash
#
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
#
# This script is designed for Sun Fire LX50, V60x and V65x systems.
# It may work with other setups as long as you use the correct channel
# and interface settings. It can be used on the V20z as long as you
# specify network settings on the command line.
#
# If the wrong channel is used you could lose network access to the
# box because your BMC will be sending out bad Gratuitous ARP packets
# with the wrong MAC address. You will need to use a console or
# override your local ARP cache with the correct addr.
usage ()
{
echo "
usage: $0 -c <chan> -i <interface> [options]
$0 -c <chan> [-v|w|x|y|z address] [options]
-c channel Which BMC channel to configure [-c help for more info]
-i interface Auto-configure BMC based on interface network settings
-v address Use specified IP address
-w address Use specified Netmask address
-x address Use specified MAC address
-y address Use specified Gateway IP address
-z address Use specified Gateway MAC address
-m interface Which IPMI interface to use [default linux=open solaris=lipmi]
-p password Set BMC channel password
-s string Set SNMP community string
-a interval Set Gratuitous ARP interval, off=0, default=4
-r Reset BMC channel, zero all network settings, disable
-d Debug mode, does not make any changes
"
exit 0;
}
channel_usage ()
{
echo "
Sun Fire V60x and V65x - Linux 2.4
eth0 = channel 6, top
eth1 = channel 7, bottom
Sun Fire V60x and V65x - Linux 2.6
eth0 = channel 7, bottom
eth1 = channel 6, top
Sun Fire V60x and V65x - Solaris x86
e1000g0 = channel 7, bottom
e1000g1 = channel 6, top
Sun LX50 - Linux
eth0 = channel 7, bottom
eth1 = channel 6, top
Sun LX50 - Solaris x86
le0 = channel 7, bottom
le1 = channel 6, top
Sun Fire V20z (-i option does not apply)
channel 1
"
exit 0
}
hex_to_ip ()
{
test $# -ge 1 || return;
local HEX B1 B2 B3 B4;
HEX=`echo $1 | tr '[:lower:]' '[:upper:]'`;
H1=`echo $HEX | cut -c1-2`
H2=`echo $HEX | cut -c3-4`
H3=`echo $HEX | cut -c5-6`
H4=`echo $HEX | cut -c7-8`
B1=`echo 10 o 16 i $H1 p | dc`
B2=`echo 10 o 16 i $H2 p | dc`
B3=`echo 10 o 16 i $H3 p | dc`
B4=`echo 10 o 16 i $H4 p | dc`
echo "$B1.$B2.$B3.$B4"
}
ipmitool_lan_set ()
{
[ $# -lt 1 ] && return
local PARAM=$1
local VALUE=
[ $# -ge 2 ] && VALUE=$2
if [ $DEBUG -gt 0 ]; then
echo "Setting LAN parameter $PARAM $VALUE"
echo "$IPMITOOL -I $IPMIINTF lan set $CHANNEL $PARAM $VALUE"
return
fi
$IPMITOOL -I $IPMIINTF lan set $CHANNEL $PARAM $VALUE
}
ipmitool_lan_reset ()
{
ipmitool_lan_set "ipsrc" "static"
ipmitool_lan_set "ipaddr" "0.0.0.0"
ipmitool_lan_set "netmask" "0.0.0.0"
ipmitool_lan_set "macaddr" "00:00:00:00:00:00"
ipmitool_lan_set "defgw ipaddr" "0.0.0.0"
ipmitool_lan_set "defgw macaddr" "00:00:00:00:00:00"
ipmitool_lan_set "password"
ipmitool_lan_set "snmp" "public"
ipmitool_lan_set "arp generate" "off"
ipmitool_lan_set "access" "off"
exit 0
}
DEBUG=0
LINUX=0
SOLARIS=0
CHANNEL=0
IFACE=
PASSWORD=
SNMP=
GRATARP=8
PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin
case `uname -s` in
Linux)
IPMIINTF=open
IPMITOOL=ipmitool
PING=ping
IFCONFIG=ifconfig
ARP=arp
ROUTE=route
;;
SunOS)
IPMIINTF=lipmi
IPMITOOL=ipmiadm
PING=ping
IFCONFIG=ifconfig
ARP=arp
ROUTE=route
;;
*)
echo "Invalid OS!"
exit 1
esac
while getopts "dhri:c:m:p:s:a:v:w:x:y:z:" OPTION ; do
case "$OPTION" in
i) IFACE=$OPTARG ;;
c) CHANNEL=$OPTARG ; test X$CHANNEL = Xhelp && channel_usage ;;
m) IPMIINTF=$OPTARG ;;
p) PASSWORD=$OPTARG ;;
s) SNMP=$OPTARG ;;
a) GRATARP=$OPTARG ;;
d) DEBUG=1 ;;
v) IP_ADDRESS=$OPTARG ;;
w) IP_NETMASK=$OPTARG ;;
x) MAC_ADDRESS=$OPTARG ;;
y) GATEWAY_IP=$OPTARG ;;
z) GATEWAY_MAC=$OPTARG ;;
r) ipmitool_lan_reset ;;
h) usage ;;
*) echo "Ignoring invalid option : -$OPTARG" ;;
esac
done
if [ ! -x `which $IPMITOOL` ]; then
echo "Error: unable to find $IPMITOOL"
exit 1
fi
if [ $CHANNEL -eq 0 ]; then
echo
echo "Error: you must specify a channel with -c"
echo
exit 1
fi
if [ "$IFACE" ]; then
if ! $IFCONFIG $IFACE 2>/dev/null | grep "inet " >/dev/null 2>&1 ; then
echo
echo "Error: unable to find interface $IFACE"
echo
exit 1
fi
echo "Auto-configuring $IFACE (channel $CHANNEL)"
fi
case `uname -s` in
SunOS)
if [ X$IFACE != X ]; then
if [ X$IP_ADDRESS = X ]; then
IP_ADDRESS=`$IFCONFIG $IFACE | grep inet | awk '{print $2}'`
fi
if [ X$IP_NETMASK = X ]; then
HEX_NETMASK=`$IFCONFIG $IFACE | grep netmask | awk '{print $4}'`
IP_NETMASK=`hex_to_ip $HEX_NETMASK`
fi
if [ X$MAC_ADDRESS = X ]; then
MAC_ADDRESS=`$IFCONFIG $IFACE | grep ether | awk '{print $2}'`
fi
if [ X$GATEWAY_IP = X ]; then
GATEWAY_IP=`$ROUTE -n get default | grep gateway: | awk '{print $2}'`
fi
if [ X$GATEWAY_MAC = X ]; then
$PING -i $IFACE $GATEWAY_IP 1 >/dev/null 2>&1
GATEWAY_MAC=`$ARP $GATEWAY_IP | awk '{print $4}'`
if [ X$GATEWAY_MAC = Xno ]; then
GATEWAY_MAC=
fi
fi
fi
;;
Linux)
if [ X$IFACE != X ]; then
if [ X$IP_ADDRESS = X ]; then
IP_ADDRESS=`$IFCONFIG $IFACE | grep inet | awk -F"[:[:space:]]+" '{print $4}'`
fi
if [ X$IP_NETMASK = X ]; then
IP_NETMASK=`$IFCONFIG $IFACE | grep Bcast | awk -F"[:[:space:]]+" '{print $8}'`
fi
if [ X$MAC_ADDRESS = X ]; then
MAC_ADDRESS=`$IFCONFIG $IFACE | grep HWaddr | awk '{print $5}'`
fi
if [ X$GATEWAY_IP = X ]; then
GATEWAY_IP=`$ROUTE -n | awk '/^0.0.0.0/ {print $2}'`
fi
if [ X$GATEWAY_MAC = X ]; then
$PING -q -c1 $GATEWAY_IP >/dev/null 2>&1
GATEWAY_MAC=`$ARP -an | grep "$GATEWAY_IP[^0-9]" | awk '{print $4}'`
fi
fi
;;
esac
if [ X$IP_ADDRESS != X ]; then
ipmitool_lan_set "ipsrc" "static"
ipmitool_lan_set "ipaddr" "$IP_ADDRESS"
fi
if [ X$IP_NETMASK != X ]; then
ipmitool_lan_set "netmask" "$IP_NETMASK"
fi
if [ X$MAC_ADDRESS != X ]; then
ipmitool_lan_set "macaddr" "$MAC_ADDRESS"
fi
if [ X$GATEWAY_IP != X ]; then
ipmitool_lan_set "defgw ipaddr" "$GATEWAY_IP"
fi
if [ X$GATEWAY_MAC != X ]; then
ipmitool_lan_set "defgw macaddr" "$GATEWAY_MAC"
fi
if [ X$PASSWORD != X ]; then
ipmitool_lan_set "password" "$PASSWORD"
fi
if [ X$SNMP != X ]; then
ipmitool_lan_set "snmp" "$SNMP"
fi
if [ "$GRATARP" -ne 0 ]; then
ipmitool_lan_set "arp generate" "on"
ipmitool_lan_set "arp interval" "$GRATARP"
else
ipmitool_lan_set "arp generate" "off"
fi
echo "Setting channel authentication capabilities"
ipmitool_lan_set "auth callback,user,operator,admin" "md2,md5"
echo "Enabling channel $CHANNEL"
ipmitool_lan_set "access" "on"
ipmitool_lan_set "user"
exit 0

View File

@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright (c) 2003 Fredrik Ohrn. All Rights Reserved.
# Copyright (c) 2003-2004 Fredrik Ohrn. All Rights Reserved.
#
# See the included COPYING file for license details.
#
@ -22,20 +22,30 @@ img_dir=/usr/local/apache2/htdocs/images/graphs
# Where will the graphs show up on the webserver?
web_dir=/images/graphs
# Size of graph area (excluding title, legends etc.)
graph_width=500
graph_height=150
# Graphs to include on page
graph_daily=1
graph_weekly=1
graph_monthly=0
# No need to edit below this point.
color[0]="0000FF"
color[1]="00FF00"
color[2]="FF0000"
color[3]="FFFF00"
color[4]="FF00FF"
color[5]="00FFFF"
color[6]="4444AA"
color[7]="44AA44"
color[8]="AA4444"
color[9]="AAAA44"
color[10]="AA44AA"
color[11]="44AAAA"
color[0]="2020FF"
color[1]="20FF20"
color[2]="FF2020"
color[3]="FF21FF"
color[4]="21FFFF"
color[5]="FFFF21"
color[6]="8F21FF"
color[7]="21FF8F"
color[8]="FF8F21"
color[9]="FF2190"
color[10]="2190FF"
color[11]="90FF21"
cat << EOF
#!$rrdcgi
@ -151,38 +161,48 @@ for group in $groups ; do
fi
fi
echo "<h3>${!group_title}</h3>"
cat << EOF
<h3>${!group_title}</h3>
if [ "$graph_daily" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-daily.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--height 200
--vertical-label "${!group_unit}"
--title "Daily graph"
--width 576 ${!group} $thres
--height $graph_height
--width $graph_width ${!group} $thres
>
EOF
fi
if [ "$graph_weekly" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-weekly.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--start -7d
--height 200
--vertical-label "${!group_unit}"
--title "Weelky graph"
--width 672 ${!group} $thres
--height $graph_height
--width $graph_width ${!group} $thres
>
EOF
#<RRD::GRAPH "$img_dir/$hostname-$group-monthly.gif"
# --imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
# --lazy
# --start -30d
# --height 200
# --vertical-label "${!group_unit}"
# --title "Monthly graph"
# --width 720 ${!group} $thres
#>
#EOF
fi
if [ "$graph_monthly" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-monthly.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--start -30d
--vertical-label "${!group_unit}"
--title "Monthly graph"
--height $graph_height
--width $graph_width ${!group} $thres
>
EOF
fi
done
cat << EOF

View File

@ -0,0 +1,151 @@
#!/bin/bash
#
# Copyright (c) 2003-2004 Fredrik Ohrn. All Rights Reserved.
#
# See the included COPYING file for license details.
#
# Edit the variables
hostname=$HOSTNAME
ipmi_cmd="/usr/local/bin/ipmitool -I open"
rrd_dir="/some/dir/rrd"
# Full path to the rrdcgi executable.
rrdcgi=/usr/local/bin/rrdcgi
# Where should rrdcgi store the graphs? This path must be within the
# document root and writable by the webserver user.
img_dir=/usr/local/apache2/htdocs/images/graphs
# Where will the graphs show up on the webserver?
web_dir=/images/graphs
# Size of graph area (excluding title, legends etc.)
graph_width=500
graph_height=150
# Graphs to include on page
graph_daily=1
graph_weekly=1
graph_monthly=0
# No need to edit below this point.
color[0]="2020FF"
color[1]="20FF20"
color[2]="FF2020"
color[3]="FF21FF"
color[4]="21FFFF"
color[5]="FFFF21"
color[6]="8F21FF"
color[7]="21FF8F"
color[8]="FF8F21"
color[9]="FF2190"
color[10]="2190FF"
color[11]="90FF21"
cat << EOF
#!$rrdcgi
<html>
<head>
<title>$hostname</title>
<RRD::GOODFOR 300>
<body>
<h2>$hostname</h2>
EOF
IFS="
"
i=0
groups=
for line in `eval $ipmi_cmd -c -v sdr list full` ; do
IFS=,
split=($line)
file="$rrd_dir/$hostname-${split[0]}.rrd"
group=`echo "${split[2]}" | tr ' .-' ___`
group_color=${group}_color
if [ -z "${!group}" ] ; then
groups="$groups $group"
declare $group_color=0
group_unit=${group}_unit
declare $group_unit="${split[2]}"
fi
declare $group="${!group}
DEF:var$i=\"$file\":var:AVERAGE LINE1:var$i#${color[${!group_color}]}:\"${split[0]}\""
declare $group_color=$[ ${!group_color} + 1 ]
c=$[ c + 1 ]
i=$[ i + 1 ]
done
IFS=" "
for group in $groups ; do
group_unit=${group}_unit
IFS=,
echo "<h3>${!group_unit}</h3>"
if [ "$graph_daily" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-daily.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--vertical-label "${!group_unit}"
--title "Daily graph"
--height $graph_height
--width $graph_width ${!group}
>
EOF
fi
if [ "$graph_weekly" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-weekly.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--start -7d
--vertical-label "${!group_unit}"
--title "Weelky graph"
--height $graph_height
--width $graph_width ${!group}
>
EOF
fi
if [ "$graph_monthly" -ne 0 ] ; then
cat << EOF
<RRD::GRAPH "$img_dir/$hostname-$group-monthly.gif"
--imginfo "<img src="$web_dir/%s" width="%lu" height="%lu">"
--lazy
--start -30d
--vertical-label "${!group_unit}"
--title "Monthly graph"
--height $graph_height
--width $graph_width ${!group}
>
EOF
fi
done
cat << EOF
</body>
</html>
EOF

17
ipmitool/contrib/ipmi.init Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
echo "Setting up OpenIPMI driver..."
# load the ipmi modules
modprobe ipmi_msghandler
modprobe ipmi_devintf
if ! modprobe ipmi_kcs_drv ; then
modprobe ipmi_si # try new module name
fi
maj=$(cat /proc/devices | awk '/ipmidev/{print $1}')
if [ "$maj" ]; then
test -e /dev/ipmi0 && rm -f /dev/ipmi0
/bin/mknod /dev/ipmi0 c $maj 0
fi

View File

@ -0,0 +1,41 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = pkginfo.in prototype.in ipmitool.spec.in \
rpmrc rpmmacros
dist-hook: pkginfo prototype

View File

@ -0,0 +1,149 @@
Name: ipmitool
Summary: ipmitool - Utility for IPMI control
Version: @VERSION@
Release: 1%{?_distro:.%{_distro}}
Copyright: BSD
Group: Utilities
Packager: Duncan Laurie <duncan@iceblink.org>
Source: ipmitool-@VERSION@.tar.gz
Buildroot: /var/tmp/ipmitool-root
%description
This package contains a utility for interfacing with devices that support
the Intelligent Platform Management Interface specification. IPMI is
an open standard for machine health, inventory, and remote power control.
This utility can communicate with IPMI-enabled devices through either a
kernel driver such as OpenIPMI or over the RMCP LAN protocol defined in
the IPMI specification. IPMIv2 adds support for encrypted LAN
communications and remote Serial-over-LAN functionality.
It provides commands for reading the Sensor Data Repository (SDR) and
displaying sensor values, displaying the contents of the System Event
Log (SEL), printing Field Replaceable Unit (FRU) information, reading and
setting LAN configuration, and chassis power control.
%prep
if [ "$RPM_BUILD_ROOT" ] && [ "$RPM_BUILD_ROOT" != "/" ]; then
rm -rf $RPM_BUILD_ROOT
fi
%setup
%build
./configure --with-kerneldir \
--prefix=%{_prefix} \
--bindir=%{_bindir} \
--datadir=%{_datadir} \
--includedir=%{_includedir} \
--libdir=%{_libdir} \
--mandir=%{_mandir} \
--sysconfdir=%{_sysconfdir}
make
%install
make DESTDIR=$RPM_BUILD_ROOT install-strip
%clean
if [ "$RPM_BUILD_ROOT" ] && [ "$RPM_BUILD_ROOT" != "/" ]; then
rm -rf $RPM_BUILD_ROOT
fi
rm -rf $RPM_BUILD_DIR/ipmitool-@VERSION@
%files
%defattr(-,root,root)
%{_bindir}/*
%{_datadir}/ipmitool/*
%doc %{_mandir}/man1/*
%doc %{_datadir}/doc/ipmitool/*
%changelog
* Wed Aug 18 2004 <duncan@iceblink.org> 1.6.0-1
- Add a README
- Add support for IPMIv2 and Serial-over-LAN from Newisys
- Add Solaris x86 lipmi interface
- Add support for building Solaris packages
- Add support for building RPMs as non-root user
- Fix segfault when doing "sel list" (from Matthew Braithwaite)
- Fix "chassis identify" on some BMCs (from ebrower@sourceforge)
- Add "bmc info" and related output (from ebrower@sourceforge)
- new "shell" and "exec" commands
- lots of other contributed patches
* Sat May 27 2004 <duncan@iceblink.org> 1.5.9-1
- Add ability to get a particular sensor by name
- Add ability to set a particular sensor threshold
- Add support for displaying V2 channel authentication levels
- Add README for rrdtool scripts in contrib directory
- Improve lan interface retry handling
- Support prompting for password or reading from environment
- Move chaninfo command into channel subcommand
- Fix reservation ID handling when two sessions open to BMC
- Fix reading of large FRU data
- Add configure option for changing binary to ipmiadm for Solaris
- Fix compile problem on Solaris 8
* Tue Jan 27 2004 <duncan@iceblink.org> 1.5.8-1
- Enable static compilation of interfaces
- Fix types to be 64-bit safe
- Fix compilation problems on Solaris
- Fix multiple big-endian problems for Solaris/SPARC
- Fix channel access to save settings to NVRAM
- Set channel privilege limit to ADMIN during "access on"
- Enable gratuitous ARP in bmcautoconf.sh
- Add support for Linux kernel panic messages in SEL output
- Add support for type 3 SDR records
* Mon Jan 5 2004 <duncan@iceblink.org> 1.5.7-1
- add IPMIv1.5 eratta fixes
- additions to FRU printing and FRU multirecords
- better handling of SDR printing
- contrib scripts for creating rrdtool graphs
* Thu Dec 4 2003 <duncan@iceblink.org> 1.5.6-1
- Fix SEL event decoding for generic events
- Handle empty SEL gracefully when doing "sel list"
- Fix sdr handling of sensors that do not return a reading
- Fix for CSV display of sensor readings/units from Fredrik <EFBFBD>hrn
* Tue Nov 25 2003 <duncan@iceblink.org> 1.5.5-1
- Add -U option for setting LAN username
- Fix -v usage for plugin interfaces
* Fri Nov 14 2003 <duncan@iceblink.org> 1.5.4-1
- pull interface plugin api into library
- fix ipmievd
* Fri Oct 31 2003 <duncan@iceblink.org> 1.5.3-1
- add -g optin for pedantic ipmi-over-lan communication
* Fri Oct 24 2003 <duncan@iceblink.org> 1.5.2-1
- add gratuitous arp interval setting
* Wed Oct 8 2003 <duncan@iceblink.org> 1.5.1-1
- better SEL support
- fix display bug in SDR list
* Fri Sep 5 2003 <duncan@iceblink.org> 1.5.0-1
- use automake/autoconf/libtool
- dynamic loading interface plugins
* Wed May 28 2003 <duncan@iceblink.org> 1.4.0-1
- make UDP packet handling more robust
- fix imb driver support
* Thu May 22 2003 <duncan@iceblink.org> 1.3-1
- update manpage
- rework of low-level network handling
- add basic imb driver support
* Wed Apr 2 2003 <duncan@iceblink.org> 1.2-1
- change command line option parsing
- support for more chassis commands
* Tue Apr 1 2003 <duncan@iceblink.org> 1.1-1
- minor fixes.
* Sun Mar 30 2003 <duncan@iceblink.org> 1.0-1
- Initial release.

View File

@ -0,0 +1,10 @@
PKG="@PACKAGE@"
NAME="@PACKAGE@ - Utility for Intelligent Platform Management Interface (IPMI) control"
ARCH="@ARCH@"
VERSION="@VERSION@"
CATEGORY="system"
VENDOR="Duncan Laurie"
EMAIL="duncan@sun.com"
PSTAMP="@PSTAMP@"
BASEDIR="@BASEDIR@"
CLASSES="none"

View File

@ -0,0 +1,7 @@
i pkginfo
d none bin ? ? ?
f none bin/@PACKAGE@=../src/@PACKAGE@ 0755 root bin
d none share ? ? ?
d none share/man ? ? ?
d none share/man/man1 ? ? ?
f none share/man/man1/@PACKAGE@.1=../doc/@PACKAGE@.1 0644 root bin

View File

@ -0,0 +1,11 @@
%_topdir %(echo $BUILDDIR)
%_sourcedir %{_topdir}/..
%_specdir %{_sourcedir}
%_tmppath %{_topdir}/tmp
%_builddir %{_topdir}/BUILD
%_buildroot %{_topdir}/%{_tmppath}/%{name}-%{version}-root
%_rpmdir %{_topdir}/RPMS
%_srcrpmdir %{_topdir}/SRPMS
%_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
%packager duncan@iceblink.org
%distribution Sourceforge Build

1
ipmitool/control/rpmrc Normal file
View File

@ -0,0 +1 @@
macrofiles: /usr/lib/rpm/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.specspo:/etc/rpm/macros:/etc/rpm/%{_target}/macros:%(echo $CONFIGDIR)/rpmmacros

View File

@ -1,3 +1,34 @@
ipmitool (1.6.0) unstable; urgency=low
* Add a README
* Add support for IPMIv2 and Serial-over-LAN from Newisys
* Add Solaris x86 lipmi interface
* Add support for building Solaris packages
* Add support for building RPMs as non-root user
* Fix segfault when doing "sel list" (from Matthew Braithwaite)
* Fix "chassis identify" on some BMCs (from ebrower@sourceforge)
* Add "bmc info" and related output (from ebrower@sourceforge)
* new "shell" and "exec" commands
* lots of other contributed patches
-- Duncan Laurie <duncan@iceblink.org> Thu, 9 Sep 2004 21:39:37 -0700
ipmitool (1.5.9) unstable; urgency=low
* Add ability to get a particular sensor by name
* Add ability to set a particular sensor threshold
* Add support for displaying V2 channel authentication levels
* Add README for rrdtool scripts in contrib directory
* Improve lan interface retry handling
* Support prompting for password or reading from environment
* Move chaninfo command into channel subcommand
* Fix reservation ID handling when two sessions open to BMC
* Fix reading of large FRU data
* Add configure option for changing binary to ipmiadm for Solaris
* Fix compile problem on Solaris 8
-- Duncan Laurie <duncan@sun.com> Sat, 27 Mar 2004 00:11:37 -0700
ipmitool (1.5.8) unstable; urgency=low
* Enable static compilation of interfaces

View File

@ -1,12 +1,12 @@
Source: ipmitool
Section: contrib
Priority: optional
Maintainer: Duncan Laurie <duncan@sun.com>
Maintainer: Duncan Laurie <duncan@iceblink.org>
Build-Depends: debhelper (>> 3.0.0)
Standards-Version: 3.5.8
Package: ipmitool
Architecture: i386
Architecture: i386 amd64
Provides: ipmitool
Description: Utility for IPMI control with kernel driver or LAN interface

View File

@ -1,2 +1,3 @@
usr/bin
usr/include/ipmitool
usr/share/ipmitool
usr/share/doc/ipmitool

4
ipmitool/debian/docs Normal file
View File

@ -0,0 +1,4 @@
README
COPYING
AUTHORS
ChangeLog

View File

@ -19,10 +19,7 @@ configure: configure-stamp
configure-stamp:
dh_testdir
./configure --prefix=/usr \
--with-pluginpath=/usr/lib/ipmitool \
--enable-intf-lan=static \
--enable-intf-open=static \
--enable-ipmievd \
--with-kerneldir \
--mandir=/usr/share/man
touch configure-stamp
@ -82,7 +79,7 @@ binary-common:
dh_testdir
dh_testroot
# dh_installdebconf
# dh_installdocs
dh_installdocs
# dh_installexamples
# dh_installmenu
# dh_installemacsen

View File

@ -37,3 +37,4 @@ MAINTAINERCLEANFILES = Makefile.in
man_MANS = ipmitool.1
EXTRA_DIST = $(man_MANS)

View File

@ -2,14 +2,20 @@
.SH "NAME"
.LP
ipmitool \- utility for controlling IPMI-enabled devices
.SH "SYNTAX"
.SH "SYNOPSIS"
.LP
ipmitool [\fB\-ghcvV\fR] \fB\-I\fR \fIlan\fP \fB\-H\fR \fIhostname\fP [\fB\-P\fR \fIpassword\fP] <\fIexpression\fP>
.br
ipmitool [\fB\-ghcvV\fR] \fB\-I\fR \fIlan\fP \fB\-H\fR \fIhostname\fP [\fB\-L\fR \fIprivlvl\fP] [\fB\-a\fR|\fB\-E\fR|\fB\-P\fR \fIpassword\fP] <\fIexpression\fP>
.LP
ipmitool [\fB\-ghcvV\fR] \fB\-I\fR \fIlanplus\fP \fB\-H\fR \fIhostname\fP [\fB\-L\fR \fIprivlvl\fP] [\fB\-a\fR|\fB\-E\fR|\fB\-P\fR \fIpassword\fP] <\fIexpression\fP>
.LP
ipmitool [\fB\-ghcvV\fR] \fB\-I\fR \fIopen\fP <\fIexpression\fP>
.SH "DESCRIPTION"
.LP
This program lets you perform various IPMI functions with either a kernel device driver or over a LAN interface. These functions include printing FRU information, LAN configuration, sensor readings, and remote chassis power control.
This program lets you manage Intelligent Platform Management Interface
(IPMI) functions of either the local system, via a kernel device driver,
or a remote system, using IPMI V1.5 . These functions include printing
FRU information, LAN configuration, sensor readings, and remote chassis
power control.
.SH "OPTIONS"
.LP
.TP
@ -17,28 +23,37 @@ This program lets you perform various IPMI functions with either a kernel device
Get basic usage help from the command line.
.TP
\fB\-c\fR
Make output suitable for parsing where possible by separating fields with commas instead of spaces.
.TP
\fB\-g\fR
Attempt to be extra robust in IPMI-over-LAN communications.
Display output with comma field separator instead of spaces. Not available with all commands.
.TP
\fB\-V\fR
Display version information.
.TP
\fB\-v\fR
Increase verbose output level. This option may be specified multiple times to increase the level of debug output. If given three times you will get hexdumps of all incoming and outgoing packets.
Increase verbose output level. This option may be specified multiple times to increase the level of debug output.
.TP
\fB\-I\fR <\fIinterface\fP>
Selects IPMI interface to use. Possible interfaces are \fIlan\fP or \fIopen\fP.
Selects IPMI interface to use. Possible interfaces are \fIlan\fP, \fIlanplus\fP or \fIopen\fP.
.TP
\fB\-H\fR <\fIaddress\fP>
Remote server address, can be IP address or hostname. This option is required for the LAN interface connection.
.TP
\fB\-P\fR <\fIpassword\fP>
Remote server password, 16 character maximum. This is optional for the LAN interface, if it is not provided the session will not be authenticated.
.TP
\fB\-U\fR <\fIusername\fP>
Remote username, default is NULL user.
.TP
\fB\-L\fR <\fIprivlvl\fP>
Force sessin privilege level. Can be CALLBACK, USER, OPERATOR, ADMIN. Default is USER.
.TP
\fB\-a\fR
Promt for the remote server password, 16 character maximum. This is optional for the LAN interface, if a password is not provided the session will not be authenticated.
.TP
\fB\-E\fR
The remote server password is specified by the environment variable \fBIPMI_PASSWORD\fR. This option is intended for shell scripts.
.TP
\fB\-f\fR <\fIfile\fP>
Read remote server password from file.
.TP
\fB\-P\fR <\fIpassword\fP>
Remote server password. \fBNote!\fR Specifying the password as a commandline option is not recommended since it will be visible in the process list.
.SH "EXPRESSIONS"
.LP
.TP
@ -48,12 +63,12 @@ This can be used to get command-line help on ipmitool commands. It may also be
.PP
ipmitool -I open help
.br
Commands: chassis, fru, lan, sdr, sel
Commands: bmc, chassis, event, fru, lan, raw, sdr, sel, sensor, sol, isol, userinfo, channel
.LP
.PP
ipmitool -I open chassis help
.br
Chassis Commands: status, power, identify, policy, restart_cause
Chassis Commands: status, power, identify, policy, restart_cause, poh
.LP
.PP
ipmitool -I open chassis power help
@ -66,7 +81,7 @@ Chassis Power Commands: status, on, off, cycle, reset, diag, soft
This will allow you to execute raw IPMI commands. For example to query the POH counter with a raw command:
.RS
.PP
ipmitool -I open raw 0x0 0xf
ipmitool -v -I open raw 0x0 0xf
.br
RAW REQ (netfn=0x0 cmd=0xf data_len=0)
.br
@ -76,7 +91,28 @@ RAW RSP (5 bytes)
.LP
.RE
.TP
\fIchaninfo\fP [\fBchannel\fR]
.I channel
.RS
.TP
\fIauthcap\fP <\fBchannel number\fR> <\fBmax priv\fR>
This command will display information about the authentication capabilities of the slected channel at the specified privelige level.
.RS
.TP
Possible privelige levels are:
.br
1 Callback level
.br
2 User level
.br
3 Operator level
.br
4 Administrator level
.br
5 OEM Proprietary level
.LP
.RE
.TP
\fIinfo\fP [\fBchannel number\fR]
This command will display information about the selected channel. If no channel is given it will display information about the currently used channel:
.RS
.PP
@ -96,11 +132,11 @@ Channel 0xf info:
.LP
.RE
.TP
\fIuserinfo\fP <\fBchannel\fR>
This command will display information about configured user information on a specific LAN channel. This command will fail on system interfaces. Try channel 6 or 7.
\fIuser\fP <\fBchannel number\fR> [\fBuser number\fR]
This command will display information about configured user information on a specific LAN channel. This command will fail on system interfaces.
.RS
.PP
ipmitool -I open userinfo 6
ipmitool -I open channel user 6
.br
Maximum User IDs : 4
.br
@ -115,6 +151,7 @@ Link Authentication : disabled
IPMI Messaging : enabled
.LP
.RE
.RE
.TP
.I chassis
.RS
@ -209,6 +246,9 @@ Set the backup gateway MAC address.
\fIpassword\fP <\fBpass\fR>
Set the null user password.
.TP
\fIsnmp\fP <\fBcommunity string\fR>
Set the SNMP community string.
.TP
\fIuser\fP
Enable user access mode.
.TP
@ -263,10 +303,43 @@ This command will read all Field Replacable Unit inventory data and extract such
.I sdr
.RS
.TP
.I info
This command will query the BMC for information about the SDR.
.TP
.I list
This command will read the SDR and extract sensor information, then query each sensor and print its name, reading, and status.
.RE
.TP
.I sensor
.RS
.TP
.I list
This command will list sensors and thresholds in a wide table format.
.TP
\fIget\fP <\fBid\fR> ... [\fBid\fR]
This command will print info for sensors specified by name.
.TP
\fIthresh\fP <\fBid\fR> <\fBthreshold\fR> <\fBsetting\fR>
This allows you to set a particular sensor threshold value. The sensor is specified by name.
.RS
.TP
Valid thresholds are:
.br
unr Upper Non-Recoverable
.br
ucr Upper Critical
.br
unc Uperr Non-Critical
.br
lnc Lower Non-Critical
.br
lcr Lower Critical
.br
lnr Lower Non-Recoverable
.LP
.RE
.RE
.TP
.I sel
.RS
.TP
@ -280,11 +353,107 @@ This command will clear the contents of the SEL. It cannot be undone so be care
This command will list the contents of the SEL.
.RE
.TP
.I session
.RS
.TP
\fIinfo\fP <\fBparameter\fR> [\fBargument\fR]
This command will query the BMC for information about its session capabilities and current sessions. Valid parameters are:
.RS
.TP
\fIactive\fP
Queries the BMC for information about the current session. That is, the session used to execute this command.
.TP
\fIall\fP
Queries the BMC for information about all active sessions
.TP
\fIid\fP <\fBid\fR>
Queries the BMC for information about the session with the specified ID. The ID should be specified in hex.
.TP
\fIhandle\fP <\fBhandle\fR>
Queries the BMC for information about the session with the specified handle. The handle should be specified in hex.
.RE
.RE
.TP
.I sol
.RS
.TP
\fIinfo\fP [\fBchannel\fR]
Retrieve information about the Serial-Over-LAN configuration on the specified channel. If no channel is given, it will display SOL configuration data for the currently used channel.
.RE
.RS
.TP
\fIset\fP <\fBparameter\fR> <\fBvalue\fR> [\fBchannel\fR]
Configure parameters for Serial Over Lan. If no channel is given, it will display SOL configuration data for the currently used channel. Configuration parameter updates are automatically guarded with the updates to the set-in-progress parameter.
.RS
.TP
Valid parameters and values are:
.br
.TP
set-in-progress
set-complete set-in-progress commit-write
.TP
enabled
true false
.TP
force-encryption
true false
.TP
force-authentication
true false
.TP
privilege-level
user operator admin oem
.TP
character-accumulate-level
Decimal number given in 5 milliseconds increments
.TP
character-send-threshold
Decimal number
.TP
retry-count
Decimal number. 0 indicates no retries after packet is transmitted.
.TP
retry-interval
Decimal number in 10 millisend increments. 0 indicates that retries should be sent back to back.
.TP
non-volatile-bit-rate
serial, 19.2, 38.4, 57.6, 115.2. Setting this value to serial indiates that the BMC should use the setting used by the IPMI over serial channel.
.TP
volatile-bit-rate
serial, 19.2, 38.4, 57.6, 115.2. Setting this value to serial indiates that the BMC should use the setting used by the IPMI over serial channel.
.LP
.RE
.RE
.RS
.TP
.I activate
This command causes ipmitool to enter Serial Over LAN mode, and is only available when using the lanplus interface. An RMCP+ connection is made to the BMC, the terminal is set to raw mode, and user input is sent to the serial console on the remote server. On exit, the the SOL payload mode is deactivated and the terminal is reset to its original settings.
.RS
.TP
Special escape sequences are provided to control the SOL session:
~. Terminate connection
.br
~^Z Suspend ipmitool
.br
~B Send break
.br
~~ Send the escape character by typing it twice
.br
~? Print the supported escape sequences
.LP
.RE
.RE
.RS
.TP
.I deactivate
This command deactives Serial Over LAN mode on the BMC. Exiting Serial Over LAN mode should automatically cause this command to be sent to the BMC, but in the case of an unintentional exit from SOL mode, this command may be necessary to reset the state the BMC.
.RE
.RE
.I isol
.RS
.TP
.I setup
Setup Serial-over-LAN: enable, set authentication and baud rate.
Setup Serial-over-LAN: enable, setup authentication and set baud rate to 19200. This sub-command is specific to Intel motherboards.
.RE
.SH "OPEN INTERFACE"
.LP
@ -305,9 +474,16 @@ Once they are loaded there will be a dynamic char device entry that must exist a
.LP
.I mknod /dev/ipmi0 c 254 0
.LP
In order to force ipmitool to make use of the device interface you can specifiy it on the command line:
In order to force ipmitool to make use of the OpenIPMI device interface you can specifiy it on the command line:
.PP
ipmitool \-I open <expression>
.SH "LIPMI INTERFACE"
.LP
The ipmitool \fIlipmi\fP interface uses the Solaris x86 IPMI kernel device driver.
.LP
You can tell ipmitool to use the Solaris IPMI driver with the \fB-I\fR option:
.PP
ipmitool \-I lipmi <expression>
.SH "LAN INTERFACE"
.LP
The ipmitool \fIlan\fP interface communicates with the BMC over an Ethernet LAN connection using UDP under IPv4. UDP datagrams are formatted to contain IPMI request/response messages with a IPMI session headers and RMCP headers.
@ -318,9 +494,20 @@ The LAN interface is an authenticatiod multi\-session connection; messages deliv
.LP
You can tell ipmitool to use the lan interface with the \fB\-I\fR option:
.PP
ipmitool \-I lan \-H <hostname> \-P [password] <expression>
ipmitool \-I lan \-H <hostname> [\-U username] [\-P password] <expression>
.LP
A hostname \fBmust\fR be given on the command line in order to use the lan interface with ipmitool. The password field is optional; if you do not provide a password on the command line ipmitool will attempt to connect without authentication. If you specify a password it will use MD5 authentication if supported by the BMC and straight password/key otherwise.
.SH "LANPLUS INTERFACE"
.LP
Like the \fIlan\fP inteface, the \fIlanplus\fP interface communicates with the BMC over an Ethernet LAN connection using UDP under IPv4. The difference is that the \fIlanplus\fP interface uses the RMCP+ protocol as described in the IMPI v2.0 specification. RMCP+ allows for improved authentication and data integrity checks, as well as encryption and the ability to carry multiple types of payloads. Generic Serial Over LAN support requires RMCP+, so the ipmitool \fIsol activate\fP command requires the use of the \fIlanplus\fP interface.
.LP
RMCP+ session establishment uses a protocol call RAKP (Remote Authenticated Key-Exchange Protocol) which allows the negotiation of many options. ipmitool does not yet allow the user to specify the value of every option, defaulting to the most obvious settings, marked as required in the v2.0 specification. Authentication and integrity HMACS are produced with SHA1, and encryption is performed with AES-CBC-128. Role-level logins are not supported. ipmitool must be configured with the appropriate option for the \fIlanplus\fP interface to be available, as it is not enabled by default. This interface currently requires the OpenSSL library.
.LP
You can tell ipmitool to use the lanplus interface with the \fB\-I\fR option:
.PP
ipmitool \-I lanplus \-H <hostname> [\-U username] [\-P password] <expression>
.LP
The options available for the \fIlanplus\fP inteface are identical to those available for the \fIlan\fP inteface.
.SH "FILES"
.TP
.I /dev/ipmi0
@ -338,7 +525,7 @@ ipmitool \-I lan \-H 192.168.1.1 \-P password chassis power status
Chassis Power is on
.SH "AUTHOR"
.LP
Duncan Laurie <duncan@sun.com>
Duncan Laurie <duncan@iceblink.org>
.SH "SEE ALSO"
.LP
.TP
@ -350,3 +537,4 @@ http://www.intel.com/design/servers/ipmi/spec.htm
.TP
OpenIPMI project (MontaVista IPMI kernel driver)
http://openipmi.sourceforge.net

View File

@ -34,9 +34,9 @@
MAINTAINERCLEANFILES = Makefile.in
ipmitooldir = $(includedir)/ipmitool
ipmitool_HEADERS = bswap.h helper.h ipmi.h ipmi_intf.h \
noinst_HEADERS = log.h bswap.h helper.h ipmi.h ipmi_intf.h \
ipmi_chassis.h ipmi_entity.h ipmi_fru.h ipmi_lanp.h \
ipmi_sdr.h ipmi_sel.h ipmi_sol.h ipmi_bmc.h ipmi_sensor.h
ipmi_sdr.h ipmi_sel.h ipmi_sol.h ipmi_bmc.h ipmi_raw.h \
ipmi_channel.h ipmi_sensor.h ipmi_event.h ipmi_session.h \
ipmi_strings.h ipmi_constants.h ipmi_isol.h ipmi_user.h

View File

@ -45,8 +45,6 @@
# include <byteswap.h>
# define BSWAP_16(x) bswap_16(x)
# define BSWAP_32(x) bswap_32(x)
#elif HAVE_SYS_BYTEORDER_H
# include <sys/byteorder.h>
#else
# define BSWAP_16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
# define BSWAP_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) |\

View File

@ -37,24 +37,32 @@
#ifndef IPMI_HELPER_H
#define IPMI_HELPER_H
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
struct valstr {
unsigned short val;
const char * str;
};
const char * val2str(unsigned short val, const struct valstr * vs);
unsigned short str2val(const char * str, const struct valstr * vs);
unsigned short buf2short(unsigned char * buf);
uint32_t buf2long(unsigned char * buf);
const char * buf2str(unsigned char * buf, int len);
void printbuf(unsigned char * buf, int len, char * desc);
void printbuf(const unsigned char * buf, int len, const char * desc);
void signal_handler(int sig, void * handler);
unsigned char ipmi_csum(unsigned char * d, int s);
FILE * ipmi_open_file(const char * file, int flags);
#define ipmi_open_file_read(file) ipmi_open_file(file, 0)
#define ipmi_open_file_write(file) ipmi_open_file(file, 1)
#define SIG_IGNORE(s) ((void)signal((s), SIG_IGN))
#define SIG_DEFAULT(s) ((void)signal((s), SIG_DFL))
#define SIG_HANDLE(s,h) ((void)signal_handler((s), (h)))
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif /* IPMI_HELPER_H */

View File

@ -39,28 +39,26 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <ipmitool/helper.h>
#define BUF_SIZE 256
#define IPMI_BUF_SIZE 1024
/* From table 13.16 of the IPMI v2 specification */
#define IPMI_PAYLOAD_TYPE_IPMI 0x00
#define IPMI_PAYLOAD_TYPE_SOL 0x01
#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST 0x10
#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE 0x11
#define IPMI_PAYLOAD_TYPE_RAKP_1 0x12
#define IPMI_PAYLOAD_TYPE_RAKP_2 0x13
#define IPMI_PAYLOAD_TYPE_RAKP_3 0x14
#define IPMI_PAYLOAD_TYPE_RAKP_4 0x15
extern int verbose;
extern int csv_output;
struct ipmi_session {
unsigned char username[16];
unsigned char challenge[16];
unsigned char password;
unsigned char authtype;
unsigned char authcode[16];
unsigned char privlvl;
uint32_t in_seq;
uint32_t out_seq;
uint32_t id;
int active;
};
struct ipmi_rq {
struct {
unsigned char netfn;
@ -70,46 +68,167 @@ struct ipmi_rq {
} msg;
};
/*
* This is what the sendrcv_v2() function would take as an argument. The common case
* is for payload_type to be IPMI_PAYLOAD_TYPE_IPMI.
*/
struct ipmi_v2_payload {
unsigned short payload_length;
unsigned char payload_type;
union {
struct {
unsigned char rq_seq;
struct ipmi_rq * request;
} ipmi_request;
struct {
unsigned char rs_seq;
struct ipmi_rs * response;
} ipmi_response;
/* Only used internally by the lanplus interface */
struct {
unsigned char * request;
} open_session_request;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_1_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_2_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_3_message;
/* Only used internally by the lanplus interface */
struct {
unsigned char * message;
} rakp_4_message;
struct {
unsigned char data[IPMI_BUF_SIZE];
unsigned short character_count;
unsigned char packet_sequence_number;
unsigned char acked_packet_number;
unsigned char accepted_character_count;
unsigned char is_nack; /* bool */
unsigned char assert_ring_wor; /* bool */
unsigned char generate_break; /* bool */
unsigned char deassert_cts; /* bool */
unsigned char deassert_dcd_dsr; /* bool */
unsigned char flush_inbound; /* bool */
unsigned char flush_outbound; /* bool */
} sol_packet;
} payload;
};
struct ipmi_rq_entry {
struct ipmi_rq req;
struct ipmi_intf * intf;
struct ipmi_session * session;
unsigned char rq_seq;
unsigned char * msg_data;
int msg_len;
struct ipmi_rq_entry * next;
};
struct ipmi_rs {
unsigned char ccode;
unsigned char data[BUF_SIZE];
unsigned char data[IPMI_BUF_SIZE];
/*
* Looks like this is the length of the entire packet, including the RMCP
* stuff, then modified to be the length of the extra IPMI message data
*/
int data_len;
struct {
unsigned char authtype;
uint32_t seq;
uint32_t id;
} session;
unsigned char msglen;
struct {
unsigned char rq_addr;
unsigned char netfn;
unsigned char rq_lun;
unsigned char rs_addr;
unsigned char rq_seq;
unsigned char rs_lun;
unsigned char cmd;
} header;
unsigned char seq;
unsigned char lun;
} msg;
struct {
unsigned char authtype;
uint32_t seq;
uint32_t id;
unsigned char bEncrypted; /* IPMI v2 only */
unsigned char bAuthenticated; /* IPMI v2 only */
unsigned char payloadtype; /* IPMI v2 only */
/* This is the total length of the payload or
IPMI message. IPMI v2.0 requires this to
be 2 bytes. Not really used for much. */
unsigned short msglen;
} session;
/*
* A union of the different possible payload meta-data
*/
union {
struct {
unsigned char rq_addr;
unsigned char netfn;
unsigned char rq_lun;
unsigned char rs_addr;
unsigned char rq_seq;
unsigned char rs_lun;
unsigned char cmd;
} ipmi_response;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned char max_priv_level;
unsigned int console_id;
unsigned int bmc_id;
unsigned char auth_alg;
unsigned char integrity_alg;
unsigned char crypt_alg;
} open_session_response;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned int console_id;
unsigned char bmc_rand[16]; /* Random number generated by the BMC */
unsigned char bmc_guid[16];
unsigned char key_exchange_auth_code[20];
} rakp2_message;
struct {
unsigned char message_tag;
unsigned char rakp_return_code;
unsigned int console_id;
unsigned char integrity_check_value[20];
} rakp4_message;
struct {
unsigned char packet_sequence_number;
unsigned char acked_packet_number;
unsigned char accepted_character_count;
unsigned char is_nack; /* bool */
unsigned char transfer_unavailable; /* bool */
unsigned char sol_inactive; /* bool */
unsigned char transmit_overrun; /* bool */
unsigned char break_detected; /* bool */
} sol_packet;
} payload;
};
struct ipmi_intf {
int fd;
struct sockaddr_in addr;
int abort;
int pedantic;
int (*open)(struct ipmi_intf *, char *, int, char *, char *);
void (*close)(struct ipmi_intf *);
struct ipmi_rs *(*sendrecv)(struct ipmi_intf *, struct ipmi_rq *);
};
#define IPMI_NETFN_CHASSIS 0x0
#define IPMI_NETFN_BRIDGE 0x2
@ -118,11 +237,11 @@ struct ipmi_intf {
#define IPMI_NETFN_FIRMWARE 0x8
#define IPMI_NETFN_STORAGE 0xa
#define IPMI_NETFN_TRANSPORT 0xc
#define IPMI_NETFN_SOL 0x34
#define IPMI_NETFN_ISOL 0x34
#define IPMI_BMC_SLAVE_ADDR 0x20
#define IPMI_REMOTE_SWID 0x81
const struct valstr completion_code_vals[25];
extern const struct valstr completion_code_vals[25];
#endif /* IPMI_H */

View File

@ -43,7 +43,44 @@
#define BMC_COLD_RESET 0x02
#define BMC_WARM_RESET 0x03
#define BMC_GET_SELF_TEST 0x04
#define BMC_SET_GLOBAL_ENABLES 0x2e
#define BMC_GET_GLOBAL_ENABLES 0x2f
int ipmi_bmc_main(struct ipmi_intf *, int, char **);
/*
* Response data from IPM Get Device ID Command (IPMI rev 1.5, section 17.1)
* The following really apply to any IPM device, not just BMCs...
*/
struct ipm_devid_rsp {
unsigned char device_id;
unsigned char device_revision;
unsigned char fw_rev1;
unsigned char fw_rev2;
unsigned char ipmi_version;
unsigned char adtl_device_support;
unsigned char manufacturer_id[3];
unsigned char product_id[2];
unsigned char aux_fw_rev[4];
} __attribute__ ((packed));
#define IPM_DEV_DEVICE_ID_SDR_MASK (0x80) /* 1 = provides SDRs */
#define IPM_DEV_DEVICE_ID_REV_MASK (0x07) /* BCD-enoded */
#define IPM_DEV_FWREV1_AVAIL_MASK (0x80) /* 0 = normal operation */
#define IPM_DEV_FWREV1_MAJOR_MASK (0x3f) /* Major rev, BCD-encoded */
#define IPM_DEV_IPMI_VER_MAJOR_MASK (0x0F) /* Major rev, BCD-encoded */
#define IPM_DEV_IPMI_VER_MINOR_MASK (0xF0) /* Minor rev, BCD-encoded */
#define IPM_DEV_IPMI_VER_MINOR_SHIFT (4) /* Minor rev shift */
#define IPM_DEV_IPMI_VERSION_MAJOR(x) \
(x & IPM_DEV_IPMI_VER_MAJOR_MASK)
#define IPM_DEV_IPMI_VERSION_MINOR(x) \
((x & IPM_DEV_IPMI_VER_MINOR_MASK) >> IPM_DEV_IPMI_VER_MINOR_SHIFT)
#define IPM_DEV_MANUFACTURER_ID(x) \
((uint32_t) ((x[2] & 0x0F) << 16 | x[1] << 8 | x[0]))
#define IPM_DEV_ADTL_SUPPORT_BITS (8)
#endif /*IPMI_BMC_H*/

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_CHANNEL_H
#define IPMI_CHANNEL_H
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
#define IPMI_GET_CHANNEL_ACCESS 0x41
#define IPMI_GET_CHANNEL_INFO 0x42
#define IPMI_SET_USER_ACCESS 0x43
#define IPMI_GET_USER_ACCESS 0x44
#define IPMI_SET_USER_NAME 0x45
#define IPMI_GET_USER_NAME 0x46
#define IPMI_SET_USER_PASSWORD 0x47
/*
* The Get Authentication Capabilities response structure
* From table 22-15 of the IPMI v2.0 spec
*/
struct get_channel_auth_cap_rsp {
unsigned char channel_number;
#if WORDS_BIGENDIAN
unsigned char v20_data_available : 1; /* IPMI v2.0 data is available */
unsigned char __reserved1 : 1;
unsigned char enabled_auth_types : 6; /* IPMI v1.5 enabled auth types */
#else
unsigned char enabled_auth_types : 6; /* IPMI v1.5 enabled auth types */
unsigned char __reserved1 : 1;
unsigned char v20_data_available : 1; /* IPMI v2.0 data is available */
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved2 : 2;
unsigned char kg_status : 1; /* two-key login status */
unsigned char per_message_auth : 1; /* per-message authentication status */
unsigned char user_level_auth : 1; /* user-level authentication status */
unsigned char non_null_usernames : 1; /* one or more non-null users exist */
unsigned char null_usernames : 1; /* one or more null usernames non-null pwds */
unsigned char anon_login_enabled : 1; /* a null-named, null-pwd user exists */
#else
unsigned char anon_login_enabled : 1; /* a null-named, null-pwd user exists */
unsigned char null_usernames : 1; /* one or more null usernames non-null pwds */
unsigned char non_null_usernames : 1; /* one or more non-null users exist */
unsigned char user_level_auth : 1; /* user-level authentication status */
unsigned char per_message_auth : 1; /* per-message authentication status */
unsigned char kg_status : 1; /* two-key login status */
unsigned char __reserved2 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved3 : 6;
unsigned char ipmiv15_support : 1; /* channel supports IPMI v1.5 connections */
unsigned char ipmiv20_support : 1; /* channel supports IPMI v2.0 connections */
#else
unsigned char ipmiv20_support : 1; /* channel supports IPMI v2.0 connections */
unsigned char ipmiv15_support : 1; /* channel supports IPMI v1.5 connections */
unsigned char __reserved3 : 6;
#endif
unsigned char oem_id[3]; /* IANA enterprise number for auth type */
unsigned char oem_aux_data; /* Additional OEM specific data for oem auths */
} __attribute__ ((packed));
/*
* The Get Channel Info response structure
* From table 22-29 of the IPMI v2.0 spec
*/
struct get_channel_info_rsp {
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 4;
unsigned char channel_number : 4; /* channel number */
#else
unsigned char channel_number : 4; /* channel number */
unsigned char __reserved1 : 4;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved2 : 1;
unsigned char channel_medium : 7; /* Channel medium type per table 6-3 */
#else
unsigned char channel_medium : 7; /* Channel medium type per table 6-3 */
unsigned char __reserved2 : 1;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved3 : 3;
unsigned char channel_protocol : 5; /* Channel protocol per table 6-2 */
#else
unsigned char channel_protocol : 5; /* Channel protocol per table 6-2 */
unsigned char __reserved3 : 3;
#endif
#if WORDS_BIGENDIAN
unsigned char session_support : 2; /* Description of session support */
unsigned char active_sessions : 6; /* Count of active sessions */
#else
unsigned char active_sessions : 6; /* Count of active sessions */
unsigned char session_support : 2; /* Description of session support */
#endif
unsigned char vendor_id[3]; /* For OEM that specified the protocol */
unsigned char aux_info[2]; /* Not used*/
} __attribute__ ((packed));
/*
* The Get Channel Access response structure
* From table 22-28 of the IPMI v2.0 spec
*/
struct get_channel_access_rsp {
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 2;
unsigned char alerting : 1;
unsigned char per_message_auth : 1;
unsigned char user_level_auth : 1;
unsigned char access_mode : 3;
#else
unsigned char access_mode : 3;
unsigned char user_level_auth : 1;
unsigned char per_message_auth : 1;
unsigned char alerting : 1;
unsigned char __reserved1 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved2 : 4;
unsigned char channel_priv_limit : 4; /* Channel privilege level limit */
#else
unsigned char channel_priv_limit : 4; /* Channel privilege level limit */
unsigned char __reserved2 : 4;
#endif
} __attribute__ ((packed));
struct get_user_access_rsp {
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 2;
unsigned char max_user_ids : 6;
unsigned char __reserved2 : 2;
unsigned char enabled_user_ids : 6;
unsigned char __reserved3 : 2;
unsigned char fixed_user_ids : 6;
unsigned char __reserved4 : 1;
unsigned char callin_callback : 1;
unsigned char link_auth : 1;
unsigned char ipmi_messaging : 1;
unsigned char privilege_limit : 4;
#else
unsigned char max_user_ids : 6;
unsigned char __reserved1 : 2;
unsigned char enabled_user_ids : 6;
unsigned char __reserved2 : 2;
unsigned char fixed_user_ids : 6;
unsigned char __reserved3 : 2;
unsigned char privilege_limit : 4;
unsigned char ipmi_messaging : 1;
unsigned char link_auth : 1;
unsigned char callin_callback : 1;
unsigned char __reserved4 : 1;
#endif
} __attribute__ ((packed));
struct set_user_access_data {
#if WORDS_BIGENDIAN
unsigned char change_bits : 1;
unsigned char callin_callback : 1;
unsigned char link_auth : 1;
unsigned char ipmi_messaging : 1;
unsigned char channel : 4;
unsigned char __reserved1 : 2;
unsigned char user_id : 6;
unsigned char __reserved2 : 4;
unsigned char privilege_limit : 4;
unsigned char __reserved3 : 4;
unsigned char session_limit : 4;
#else
unsigned char channel : 4;
unsigned char ipmi_messaging : 1;
unsigned char link_auth : 1;
unsigned char callin_callback : 1;
unsigned char change_bits : 1;
unsigned char user_id : 6;
unsigned char __reserved1 : 2;
unsigned char privilege_limit : 4;
unsigned char __reserved2 : 4;
unsigned char session_limit : 4;
unsigned char __reserved3 : 4;
#endif
} __attribute__ ((packed));
int ipmi_channel_main(struct ipmi_intf *, int, char **);
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf, unsigned char channel, unsigned char priv);
int ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel);
#endif /*IPMI_CHANNEL_H*/

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_CONSTANTS_H
#define IPMI_CONSTANTS_H
/*
* COMMANDS
*/
#define IPMI_GET_SDR_REPOSITORY_INFO 0x20
#define IMPI_SOL_ACTIVATING 0x20
#define IMPI_SET_SOL_CONFIG_PARAMETERS 0x21
#define IMPI_GET_SOL_CONFIG_PARAMETERS 0x22
#define IPMI_SET_USER_ACCESS 0x43
#define IPMI_GET_USER_ACCESS 0x44
#define IPMI_SET_USER_NAME 0x45
#define IPMI_GET_USER_NAME 0x46
#define IPMI_SET_USER_PASSWORD 0x47
#define IPMI_ACTIVATE_PAYLOAD 0x48
#define IPMI_DEACTIVATE_PAYLOAD 0x49
#define IPMI_SUSPEND_RESUME_PAYLOAD_ENCRYPTYION 0x55
#define IPMI_GET_SEL_TIME 0x48
#define IPMI_SET_SEL_TIME 0x49
#define IPMI_1_5_AUTH_TYPE_BIT_NONE 0x01
#define IPMI_1_5_AUTH_TYPE_BIT_MD2 0x02
#define IPMI_1_5_AUTH_TYPE_BIT_MD5 0x04
#define IPMI_1_5_AUTH_TYPE_BIT_PASSWORD 0x10
#define IPMI_1_5_AUTH_TYPE_BIT_OEM 0x20
#define IPMI_SESSION_AUTHTYPE_NONE 0x0
#define IPMI_SESSION_AUTHTYPE_MD2 0x1
#define IPMI_SESSION_AUTHTYPE_MD5 0x2
#define IPMI_SESSION_AUTHTYPE_KEY 0x4
#define IPMI_SESSION_AUTHTYPE_PASSWORD IPMI_SESSION_AUTHTYPE_KEY
#define IPMI_SESSION_AUTHTYPE_OEM 0x5
#define IPMI_SESSION_AUTHTYPE_RMCP_PLUS 0x6
#define IPMI_SESSION_PRIV_CALLBACK 0x1
#define IPMI_SESSION_PRIV_USER 0x2
#define IPMI_SESSION_PRIV_OPERATOR 0x3
#define IPMI_SESSION_PRIV_ADMIN 0x4
#define IPMI_SESSION_PRIV_OEM 0x5
#define IPMI_SET_IN_PROGRESS_SET_COMPLETE 0x00
#define IPMI_SET_IN_PROGRESS_IN_PROGRESS 0x01
#define IPMI_SET_IN_PROGRESS_COMMIT_WRITE 0x02
#endif /*IPMI_CONSTANTS_H*/

View File

@ -34,16 +34,14 @@
* facility.
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef IPMI_EVENT_H
#define IPMI_EVENT_H
#include <config.h>
#include <ipmitool/ipmi_intf.h>
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
@STATIC_INTF_EXT@
int ipmi_event_main(struct ipmi_intf *, int, char **);
struct static_intf static_intf_list[] = {
@STATIC_INTF@
{ 0, 0 }
};
#endif /*IPMI_EVENT_H*/

View File

@ -37,7 +37,7 @@
#ifndef IPMI_FRU_H
#define IPMI_FRU_H
#include <stdint.h>
#include <inttypes.h>
#include <ipmitool/ipmi.h>
#if HAVE_CONFIG_H
@ -83,16 +83,16 @@ struct fru_header {
struct fru_area_chassis {
unsigned char area_ver;
unsigned char area_len;
unsigned char type;
unsigned short area_len;
char * part;
char * serial;
};
struct fru_area_board {
unsigned char area_ver;
unsigned char area_len;
unsigned char lang;
unsigned short area_len;
uint32_t mfg_date_time;
char * mfg;
char * prod;
@ -103,8 +103,8 @@ struct fru_area_board {
struct fru_area_product {
unsigned char area_ver;
unsigned char area_len;
unsigned char lang;
unsigned short area_len;
char * mfg;
char * name;
char * part;

View File

@ -38,14 +38,135 @@
#define IPMI_INTF_H
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_constants.h>
struct static_intf {
char * name;
int (*setup)(struct ipmi_intf ** intf);
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*
* An enumeration that describes every possible session state for
* an IPMIv2 / RMCP+ session.
*/
enum LANPLUS_SESSION_STATE {
LANPLUS_STATE_PRESESSION = 0,
LANPLUS_STATE_OPEN_SESSION_SENT,
LANPLUS_STATE_OPEN_SESSION_RECEIEVED,
LANPLUS_STATE_RAKP_1_SENT,
LANPLUS_STATE_RAKP_2_RECEIVED,
LANPLUS_STATE_RAKP_3_SENT,
LANPLUS_STATE_ACTIVE,
LANPLUS_STATE_CLOSE_SENT,
};
#define IPMI_AUTHCODE_BUFFER_SIZE 20
#define IPMI_SIK_BUFFER_SIZE 20
#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
struct ipmi_session {
unsigned char hostname[64];
unsigned char username[16];
unsigned char authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1];
unsigned char challenge[16];
unsigned char authtype;
unsigned char authtype_set;
unsigned char privlvl;
int password;
int port;
int active;
uint32_t session_id;
uint32_t in_seq;
uint32_t out_seq;
uint32_t timeout;
struct sockaddr_in addr;
socklen_t addrlen;
/*
* This struct holds state data specific to IMPI v2 / RMCP+ sessions
*/
struct {
enum LANPLUS_SESSION_STATE session_state;
/* These are the algorithms agreed upon for the session */
unsigned char auth_alg;
unsigned char integrity_alg;
unsigned char crypt_alg;
unsigned char max_priv_level;
uint32_t console_id;
uint32_t bmc_id;
/*
* Values required for RAKP mesages
*/
/* Random number generated byt the console */
unsigned char console_rand[16];
/* Random number generated by the BMC */
unsigned char bmc_rand[16];
unsigned char bmc_guid[16];
unsigned char requested_role; /* As sent in the RAKP 1 message */
unsigned char rakp2_return_code;
unsigned char sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */
unsigned char kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
unsigned char k1[20]; /* Used for Integrity checking? */
unsigned char k2[20]; /* First 16 bytes used for AES */
} v2_data;
/*
* This data is specific to the Serial Over Lan session
*/
struct {
uint16_t max_inbound_payload_size;
uint16_t max_outbound_payload_size;
uint16_t port;
unsigned char sequence_number;
/* This data describes the last SOL packet */
unsigned char last_received_sequence_number;
unsigned char last_received_byte_count;
void (*sol_input_handler)(struct ipmi_rs * rsp);
} sol_data;
};
struct ipmi_intf {
char name[16];
char desc[128];
int fd;
int opened;
int abort;
int thump;
struct ipmi_session * session;
unsigned int my_addr;
unsigned int target_addr;
int (*setup)(struct ipmi_intf * intf);
int (*open)(struct ipmi_intf * intf);
void (*close)(struct ipmi_intf * intf);
struct ipmi_rs *(*sendrecv)(struct ipmi_intf * intf, struct ipmi_rq * req);
int (*sendrsp)(struct ipmi_intf * intf, struct ipmi_rs * rsp);
struct ipmi_rs *(*recv_sol)(struct ipmi_intf * intf);
struct ipmi_rs *(*send_sol)(struct ipmi_intf * intf, struct ipmi_v2_payload * payload);
int (*keepalive)(struct ipmi_intf * intf);
};
int ipmi_intf_init(void);
void ipmi_intf_exit(void);
struct ipmi_intf * ipmi_intf_load(char * name);
void ipmi_intf_print(void);
void ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname);
void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username);
void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password);
void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, unsigned char privlvl);
void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port);
void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, unsigned char authtype);
#endif /* IPMI_INTF_H */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_ISOL_H
#define IPMI_ISOL_H
#include <ipmitool/ipmi.h>
#define ACTIVATE_ISOL 0x01
#define SET_ISOL_CONFIG 0x03
#define GET_ISOL_CONFIG 0x04
#define ISOL_ENABLE_PARAM 0x01
#define ISOL_AUTHENTICATION_PARAM 0x02
#define ISOL_ENABLE_FLAG 0x01
#define ISOL_PRIVILEGE_LEVEL_USER 0x02
#define ISOL_BAUD_RATE_PARAM 0x05
#define ISOL_PREFERRED_BAUD_RATE 0x07
int ipmi_isol_main(struct ipmi_intf *, int, char **);
#endif /* IPMI_SOL_H */

View File

@ -46,21 +46,10 @@
# define IPMI_LAN_SUSPEND_ARP_GRAT (1)
#define IPMI_LAN_GET_STAT 0x04
#define IPMI_SESSION_AUTHTYPE_NONE 0x0
#define IPMI_SESSION_AUTHTYPE_MD2 0x1
#define IPMI_SESSION_AUTHTYPE_MD5 0x2
#define IPMI_SESSION_AUTHTYPE_KEY 0x4
#define IPMI_SESSION_AUTHTYPE_OEM 0x5
#define IPMI_SESSION_PRIV_CALLBACK 0x1
#define IPMI_SESSION_PRIV_USER 0x2
#define IPMI_SESSION_PRIV_OPERATOR 0x3
#define IPMI_SESSION_PRIV_ADMIN 0x4
#define IPMI_SESSION_PRIV_OEM 0x5
#define IPMI_CHANNEL_NUMBER_MAX 0xd
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_vals[];
extern struct ipmi_session lan_session;
enum {
IPMI_LANP_SET_IN_PROGRESS,
@ -97,6 +86,7 @@ static struct lan_param {
int size;
char desc[24];
unsigned char * data;
int data_len;
} ipmi_lan_params[] __attribute__((unused)) = {
{ IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress" },
{ IPMI_LANP_AUTH_TYPE, 1, "Auth Type" },
@ -114,7 +104,7 @@ static struct lan_param {
{ IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC" },
{ IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP" },
{ IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC" },
{ IPMI_LANP_SNMP_STRING, 18, "Community String" },
{ IPMI_LANP_SNMP_STRING, 18, "SNMP Community String" },
{ IPMI_LANP_NUM_DEST, 1, "Number of Destinations"},
{ IPMI_LANP_DEST_TYPE, 4, "Destination Type" },
{ IPMI_LANP_DEST_ADDR, 13, "Destination Addresses" },
@ -128,7 +118,6 @@ static struct lan_param {
{ -1 }
};
void ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel);
int ipmi_lanp_main(struct ipmi_intf *, int, char **);
#endif /*IPMI_LANP_H*/

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_RAW_H
#define IPMI_RAW_H
#include <ipmitool/ipmi.h>
int ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv);
#endif /* IPMI_RAW_H */

View File

@ -41,7 +41,7 @@
# include <config.h>
#endif
#include <stdint.h>
#include <inttypes.h>
#include <math.h>
#include <ipmitool/bswap.h>
#include <ipmitool/ipmi.h>
@ -98,7 +98,6 @@ struct sdr_get_rq {
unsigned short id; /* record ID */
unsigned char offset; /* offset into SDR */
#define GET_SDR_ENTIRE_RECORD 0xff
#define GET_SDR_MAX_LEN 30
unsigned char length; /* length to read */
} __attribute__ ((packed));
@ -570,6 +569,41 @@ struct sdr_record_fru_locator {
unsigned char id_string[16];
} __attribute__ ((packed));
/*
* The Get SDR Repository Info response structure
* From table 33-3 of the IPMI v2.0 spec
*/
struct get_sdr_repository_info_rsp {
unsigned char sdr_version;
unsigned char record_count_lsb;
unsigned char record_count_msb;
unsigned char free_space[2];
unsigned char most_recent_addition_timestamp[4];
unsigned char most_recent_erase_timestamp[4];
#if WORDS_BIGENDIAN
unsigned char overflow_flag : 1;
unsigned char modal_update_support : 2;
unsigned char __reserved1 : 1;
unsigned char delete_sdr_supported : 1;
unsigned char partial_add_sdr_supported : 1;
unsigned char reserve_sdr_repository_supported : 1;
unsigned char get_sdr_repository_allo_info_supported : 1;
#else
unsigned char get_sdr_repository_allo_info_supported : 1;
unsigned char reserve_sdr_repository_supported : 1;
unsigned char partial_add_sdr_supported : 1;
unsigned char delete_sdr_supported : 1;
unsigned char __reserved1 : 1;
unsigned char modal_update_support : 2;
unsigned char overflow_flag : 1;
#endif
} __attribute__ ((packed));
struct ipmi_sdr_iterator
{
unsigned short reservation;
@ -577,6 +611,19 @@ struct ipmi_sdr_iterator
int next;
};
struct sdr_record_list {
unsigned short id;
unsigned char type;
struct sdr_record_list * next;
union {
struct sdr_record_full_sensor * full;
struct sdr_record_compact_sensor * compact;
struct sdr_record_eventonly_sensor * eventonly;
struct sdr_record_fru_locator * fruloc;
struct sdr_record_mc_locator * mcloc;
} record;
};
/* unit description codes (IPMI v1.5 section 37.16) */
#define UNIT_MAX 0x90
static const char * unit_desc[] __attribute__((unused)) = {
@ -627,7 +674,18 @@ void ipmi_sdr_end(struct ipmi_intf * intf, struct ipmi_sdr_iterator * i);
void ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type);
const char * ipmi_sdr_get_status(unsigned char stat);
float sdr_convert_sensor_reading(struct sdr_record_full_sensor * sensor, unsigned char val);
unsigned char sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor * sensor, float val);
struct ipmi_rs * ipmi_sdr_get_sensor_reading(struct ipmi_intf * intf, unsigned char sensor);
const char * ipmi_sdr_get_sensor_type_desc(const unsigned char type);
void ipmi_sdr_print_sensor_full(struct ipmi_intf * intf, struct sdr_record_full_sensor * sensor);
void ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf, struct sdr_record_compact_sensor * sensor);
void ipmi_sdr_print_sensor_eventonly(struct ipmi_intf * intf, struct sdr_record_eventonly_sensor * sensor);
void ipmi_sdr_print_fru_locator(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru);
void ipmi_sdr_print_mc_locator(struct ipmi_intf * intf, struct sdr_record_mc_locator * mc);
struct sdr_record_list * ipmi_sdr_find_sdr_byid(struct ipmi_intf * intf, char * id);
void ipmi_sdr_list_empty(struct ipmi_intf * intf);
int ipmi_sdr_print_info(struct ipmi_intf * intf);
#endif /* IPMI_SDR_H */

View File

@ -37,7 +37,7 @@
#ifndef IPMI_SEL_H
#define IPMI_SEL_H
#include <stdint.h>
#include <inttypes.h>
#include <ipmitool/ipmi.h>
#define IPMI_CMD_GET_SEL_INFO 0x40
@ -381,5 +381,8 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu
int ipmi_sel_main(struct ipmi_intf *, int, char **);
void ipmi_sel_print_std_entry(struct sel_event_record * evt);
void ipmi_sel_print_std_entry_verbose(struct sel_event_record * evt);
void ipmi_get_event_desc(struct sel_event_record * rec, char ** desc);
const char * ipmi_sel_get_sensor_type(unsigned char code);
#endif /* IPMI_SEL_H */

View File

@ -41,11 +41,54 @@
#include <ipmitool/bswap.h>
#include <ipmitool/ipmi.h>
/* ipmi sensor commands */
#define GET_SENSOR_READING 0x2d
#define GET_SENSOR_FACTORS 0x23
#define GET_SENSOR_THRES 0x27
#define SET_SENSOR_THRESHOLDS 0x26
#define GET_SENSOR_THRESHOLDS 0x27
#define GET_SENSOR_TYPE 0x2f
/* threshold specification bits for analog sensors for get sensor threshold command
* and set sensor threshold command
*/
#define UPPER_NON_RECOV_SPECIFIED 0x20
#define UPPER_CRIT_SPECIFIED 0x10
#define UPPER_NON_CRIT_SPECIFIED 0x08
#define LOWER_NON_RECOV_SPECIFIED 0x04
#define LOWER_CRIT_SPECIFIED 0x02
#define LOWER_NON_CRIT_SPECIFIED 0x01
/* state assertion bits for discrete sensors for get sensor reading command */
#define STATE_0_ASSERTED 0x01
#define STATE_1_ASSERTED 0x02
#define STATE_2_ASSERTED 0x04
#define STATE_3_ASSERTED 0x08
#define STATE_4_ASSERTED 0x10
#define STATE_5_ASSERTED 0x20
#define STATE_6_ASSERTED 0x40
#define STATE_7_ASSERTED 0x80
#define STATE_8_ASSERTED 0x01
#define STATE_9_ASSERTED 0x02
#define STATE_10_ASSERTED 0x04
#define STATE_11_ASSERTED 0x08
#define STATE_12_ASSERTED 0x10
#define STATE_13_ASSERTED 0x20
#define STATE_14_ASSERTED 0x40
struct sensor_set_thresh_rq {
unsigned char sensor_num; /* sensor # */
unsigned char set_mask; /* threshold setting mask */
unsigned char lower_non_crit; /* new lower non critical threshold*/
unsigned char lower_crit; /* new lower critical threshold*/
unsigned char lower_non_recov; /* new lower non recoverable threshold*/
unsigned char upper_non_crit; /* new upper non critical threshold*/
unsigned char upper_crit; /* new upper critical threshold*/
unsigned char upper_non_recov; /* new upper non recoverable threshold*/
} __attribute__ ((packed));
int ipmi_sensor_main(struct ipmi_intf *, int, char **);
void ipmi_sensor_print_full(struct ipmi_intf *, struct sdr_record_full_sensor *);
void ipmi_sensor_print_compact(struct ipmi_intf *, struct sdr_record_compact_sensor *);
#endif /* IPMI_SENSOR_H */

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_SESSION_H
#define IPMI_SESSION_H
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
#define IPMI_GET_SESSION_INFO 0x3D
/*
* From table 22.25 of the IPMIv2 specification
*/
struct get_session_info_rsp
{
unsigned char session_handle;
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 2;
unsigned char session_slot_count : 6; /* 1-based */
#else
unsigned char session_slot_count : 6; /* 1-based */
unsigned char __reserved1 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved2 : 2;
unsigned char active_session_count : 6; /* 1-based */
#else
unsigned char active_session_count : 6; /* 1-based */
unsigned char __reserved2 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved3 : 2;
unsigned char user_id : 6;
#else
unsigned char user_id : 6;
unsigned char __reserved3 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved4 : 4;
unsigned char privilege_level : 4;
#else
unsigned char privilege_level : 4;
unsigned char __reserved4 : 4;
#endif
#if WORDS_BIGENDIAN
unsigned char auxiliary_data : 4;
unsigned char channel_number : 4;
#else
unsigned char channel_number : 4;
unsigned char auxiliary_data : 4;
#endif
union
{
/* Only exists if channel type is 802.3 LAN */
struct
{
unsigned char console_ip[4]; /* MSBF */
unsigned char console_mac[6]; /* MSBF */
uint16_t console_port; /* LSBF */
} lan_data;
/* Only exists if channel type is async. serial modem */
struct
{
unsigned char session_channel_activity_type;
#if WORDS_BIGENDIAN
unsigned char __reserved5 : 4;
unsigned char destination_selector : 4;
#else
unsigned char destination_selector : 4;
unsigned char __reserved5 : 4;
#endif
unsigned char console_ip[4]; /* MSBF */
/* Only exists if session is PPP */
uint16_t console_port; /* LSBF */
} modem_data;
} channel_data;
} __attribute__ ((packed));
int ipmi_session_main(struct ipmi_intf *, int, char **);
#endif /*IPMI_CHANNEL_H*/

View File

@ -39,17 +39,48 @@
#include <ipmitool/ipmi.h>
#define ACTIVATE_SOL 0x01
#define SET_SOL_CONFIG 0x03
#define GET_SOL_CONFIG 0x04
#define SOL_ENABLE_PARAM 0x01
#define SOL_AUTHENTICATION_PARAM 0x02
#define SOL_ENABLE_FLAG 0x01
#define SOL_PRIVILEGE_LEVEL_USER 0x02
#define SOL_BAUD_RATE_PARAM 0x05
#define SOL_PREFERRED_BAUD_RATE 0x07
#define IPMI_SOL_SERIAL_ALERT_MASK_SUCCEED 0x08
#define IPMI_SOL_SERIAL_ALERT_MASK_DEFERRED 0x04
#define IPMI_SOL_SERIAL_ALERT_MASK_FAIL 0x00
#define IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE 0x00
#define IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE 0x02
struct sol_config_parameters {
unsigned char set_in_progress;
unsigned char enabled;
unsigned char force_encryption;
unsigned char force_authentication;
unsigned char privilege_level;
unsigned char character_accumulate_level;
unsigned char character_send_threshold;
unsigned char retry_count;
unsigned char retry_interval;
unsigned char non_volatile_bit_rate;
unsigned char volatile_bit_rate;
unsigned char payload_channel;
unsigned short payload_port;
};
/*
* The ACTIVATE PAYLOAD command reponse structure
* From table 24-2 of the IPMI v2.0 spec
*/
struct activate_payload_rsp {
unsigned char auxiliary_data[4];
unsigned char inbound_payload_size[2]; /* LS byte first */
unsigned char outbound_payload_size[2]; /* LS byte first */
unsigned char payload_udp_port[2]; /* LS byte first */
unsigned char payload_vlan_number[2]; /* LS byte first */
} __attribute__ ((packed));
int ipmi_sol_main(struct ipmi_intf *, int, char **);
int ipmi_get_sol_info(struct ipmi_intf * intf,
unsigned char channel,
struct sol_config_parameters * params);
#endif /* IPMI_SOL_H */

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_STRINGS_H
#define IPMI_STRINGS_H
#include <ipmitool/helper.h>
extern const struct valstr ipmi_channel_activity_type_vals[];
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr impi_bit_rate_vals[];
extern const struct valstr ipmi_set_in_progress_vals[];
extern const struct valstr ipmi_authtype_session_vals[];
extern const struct valstr ipmi_authtype_vals[];
#endif /*IPMI_STRINGS_H*/

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_USER_H
#define IPMI_USER_H
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
/*
* The GET USER ACCESS response from table 22-32 of the IMPI v2.0 spec
*/
struct user_access_rsp {
#if WORDS_BIGENDIAN
unsigned char __reserved1 : 2;
unsigned char maximum_ids : 6;
#else
unsigned char maximum_ids : 6;
unsigned char __reserved1 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved2 : 2;
unsigned char enabled_user_count : 6;
#else
unsigned char enabled_user_count : 6;
unsigned char __reserved2 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved3 : 2;
unsigned char fixed_name_count : 6;
#else
unsigned char fixed_name_count : 6;
unsigned char __reserved3 : 2;
#endif
#if WORDS_BIGENDIAN
unsigned char __reserved4 : 1;
unsigned char no_callin_access : 1;
unsigned char link_auth_access : 1;
unsigned char ipmi_messaging_access : 1;
unsigned char channel_privilege_limit : 4;
#else
unsigned char channel_privilege_limit : 4;
unsigned char ipmi_messaging_access : 1;
unsigned char link_auth_access : 1;
unsigned char no_callin_access : 1;
unsigned char __reserved4 : 1;
#endif
} __attribute__ ((packed));
int ipmi_user_main(struct ipmi_intf *, int, char **);
#endif /* IPMI_USER_H */

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMITOOL_LOG_H
#define IPMITOOL_LOG_H
#include <syslog.h>
/* sys/syslog.h:
* LOG_EMERG 0 system is unusable
* LOG_ALERT 1 action must be taken immediately
* LOG_CRIT 2 critical conditions
* LOG_ERR 3 error conditions
* LOG_WARNING 4 warning conditions
* LOG_NOTICE 5 normal but significant condition
* LOG_INFO 6 informational
* LOG_DEBUG 7 debug-level messages
*/
#define LOG_ERROR LOG_ERR
#define LOG_WARN LOG_WARNING
#define LOG_NAME_DEFAULT "ipmitool"
#define LOG_MSG_LENGTH 1024
void log_init(const char * name, int isdaemon, int verbose);
void log_halt(void);
void log_level_set(int level);
int log_level_get(void);
void lprintf(int level, const char * format, ...);
void lperror(int level, const char * format, ...);
#endif /*IPMITOOL_LOG_H*/

View File

@ -1,132 +0,0 @@
Name: @IPMITOOL_PKG@
Summary: @IPMITOOL_PKG@ - Utility for interfacing with IPMI devices
Version: @VERSION@
Release: 1
Copyright: BSD
Group: Utilities
Vendor: Sun Microsystems
Packager: Duncan Laurie <duncan@sun.com>
Source: @IPMITOOL_PKG@-@VERSION@.tar.gz
Buildroot: /var/tmp/@IPMITOOL_PKG@-root
%package dev
Summary: Development files for ipmitool
Group: Utilities
%description
This package contains a utility for interfacing with IPMI-enabled devices
through either the OpenIPMI kernel driver or with IPMI-over-LAN protocol.
It provides some basic functions for reading the SDR and displaying sensor
values, displaying the contents of the SEL, printing FRU information,
reading and setting LAN configuration, and chassis power control.
%description dev
Additional development files for creating applications or interface plugins
for ipmitool.
%prep
if [ "$RPM_BUILD_ROOT" ] && [ "$RPM_BUILD_ROOT" != "/" ]; then
rm -rf $RPM_BUILD_ROOT
fi
%setup
%build
./configure \
--enable-ipmievd \
--enable-intf-lan=static \
--enable-intf-open=static \
--with-kerneldir=/usr/src/linux-2.4 \
--prefix=%{_prefix} \
--bindir=%{_bindir} \
--datadir=%{_datadir} \
--includedir=%{_includedir} \
--libdir=%{_libdir} \
--mandir=%{_mandir} \
--sysconfdir=%{_sysconfdir}
make
%install
make DESTDIR=$RPM_BUILD_ROOT install-strip
%clean
if [ "$RPM_BUILD_ROOT" ] && [ "$RPM_BUILD_ROOT" != "/" ]; then
rm -rf $RPM_BUILD_ROOT
fi
rm -rf $RPM_BUILD_DIR/@IPMITOOL_PKG@-@VERSION@
%files
%defattr(-,root,root)
%doc %{_mandir}/man1/*
%{_bindir}/*
%files dev
%defattr(-,root,root)
%dir %{_includedir}/ipmitool
%{_includedir}/ipmitool/*.h
%changelog
* Tue Jan 27 2004 <duncan@sun.com> 1.5.8-1
- Enable static compilation of interfaces
- Fix types to be 64-bit safe
- Fix compilation problems on Solaris
- Fix multiple big-endian problems for Solaris/SPARC
- Fix channel access to save settings to NVRAM
- Set channel privilege limit to ADMIN during "access on"
- Enable gratuitous ARP in bmcautoconf.sh
- Add support for Linux kernel panic messages in SEL output
- Add support for type 3 SDR records
* Mon Jan 5 2004 <duncan@sun.com> 1.5.7-1
- add IPMIv1.5 eratta fixes
- additions to FRU printing and FRU multirecords
- better handling of SDR printing
- contrib scripts for creating rrdtool graphs
* Thu Dec 4 2003 <duncan@sun.com> 1.5.6-1
- Fix SEL event decoding for generic events
- Handle empty SEL gracefully when doing "sel list"
- Fix sdr handling of sensors that do not return a reading
- Fix for CSV display of sensor readings/units from Fredrik <EFBFBD>hrn
* Tue Nov 25 2003 <duncan@sun.com> 1.5.5-1
- Add -U option for setting LAN username
- Fix -v usage for plugin interfaces
* Fri Nov 14 2003 <duncan@sun.com> 1.5.4-1
- pull interface plugin api into library
- fix ipmievd
* Fri Oct 31 2003 <duncan@sun.com> 1.5.3-1
- add -g optin for pedantic ipmi-over-lan communication
* Fri Oct 24 2003 <duncan@sun.com> 1.5.2-1
- add gratuitous arp interval setting
* Wed Oct 8 2003 <duncan@sun.com> 1.5.1-1
- better SEL support
- fix display bug in SDR list
* Fri Sep 5 2003 <duncan@sun.com> 1.5.0-1
- use automake/autoconf/libtool
- dynamic loading interface plugins
* Wed May 28 2003 <duncan@sun.com> 1.4.0-1
- make UDP packet handling more robust
- fix imb driver support
* Thu May 22 2003 <duncan@sun.com> 1.3-1
- update manpage
- rework of low-level network handling
- add basic imb driver support
* Wed Apr 2 2003 <duncan@sun.com> 1.2-1
- change command line option parsing
- support for more chassis commands
* Tue Apr 1 2003 <duncan@sun.com> 1.1-1
- minor fixes.
* Sun Mar 30 2003 <duncan@sun.com> 1.0-1
- Initial release.

View File

@ -36,8 +36,10 @@ INCLUDES = -I$(top_srcdir)/include
MAINTAINERCLEANFILES = Makefile.in
noinst_LTLIBRARIES = libipmitool.la
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_lanp.c \
ipmi_fru.c ipmi_chassis.c ipmi_bmc.c dimm_spd.c ipmi_sensor.c
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_isol.c \
ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_bmc.c log.c \
dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \
ipmi_session.c ipmi_strings.c ipmi_user.c ipmi_raw.c
libipmitool_la_LDFLAGS = -export-dynamic
libipmitool_la_LIBADD = -lm
libipmitool_la_DEPENDENCIES =

View File

@ -35,6 +35,7 @@
*/
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_fru.h>
#include <stdlib.h>
@ -675,8 +676,7 @@ void ipmi_spd_print(struct ipmi_intf * intf, unsigned char id)
struct ipmi_rq req;
struct fru_info fru;
unsigned char spd_data[256], msg_data[4];
int i, len, offset;
int size, conf;
int len, offset, size;
msg_data[0] = id;

View File

@ -36,12 +36,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <signal.h>
#include <ipmitool/helper.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <ipmitool/helper.h>
uint32_t buf2long(unsigned char * buf)
{
@ -71,7 +75,7 @@ const char * buf2str(unsigned char * buf, int len)
return (const char *)str;
}
void printbuf(unsigned char * buf, int len, char * desc)
void printbuf(const unsigned char * buf, int len, const char * desc)
{
int i;
@ -104,6 +108,19 @@ const char * val2str(unsigned short val, const struct valstr *vs)
return un_str;
}
unsigned short str2val(const char *str, const struct valstr *vs)
{
int i = 0;
while (vs[i].str) {
if (!strncasecmp(vs[i].str, str, strlen(str)))
return vs[i].val;
i++;
}
return 0;
}
void signal_handler(int sig, void * handler)
{
struct sigaction act;
@ -126,3 +143,77 @@ void signal_handler(int sig, void * handler)
}
}
unsigned char ipmi_csum(unsigned char * d, int s)
{
unsigned char c = 0;
for (; s > 0; s--, d++)
c += *d;
return -c;
}
/* safely open a file for reading or writing
* file: filename
* rw: read-write flag, 1=write
*/
FILE * ipmi_open_file(const char * file, int rw)
{
struct stat st1, st2;
FILE * fp;
/* verify existance */
if (lstat(file, &st1) < 0) {
if (rw) {
/* does not exist, ok to create */
fp = fopen(file, "w");
if (!fp) {
printf("ERROR: Unable to open file %s for write: %s\n",
file, strerror(errno));
return NULL;
}
return fp;
} else {
printf("ERROR: File %s does not exist\n", file);
return NULL;
}
}
/* it exists - only regular files, not links */
if (!S_ISREG(st1.st_mode)) {
printf("ERROR: File %s has invalid mode: %d\n", file, st1.st_mode);
return NULL;
}
/* allow only files with 1 link (itself) */
if (st1.st_nlink != 1) {
printf("ERROR: File %s has invalid link count: %d != 1\n",
file, (int)st1.st_nlink);
return NULL;
}
fp = fopen(file, rw ? "w+" : "r");
if (!fp) {
printf("ERROR: Unable to open file %s: %s\n",
file, strerror(errno));
return NULL;
}
/* stat again */
if (fstat(fileno(fp), &st2) < 0) {
printf("ERROR: Unable to stat file %s: %s\n",
file, strerror(errno));
fclose(fp);
return NULL;
}
/* verify inode, owner, link count */
if (st2.st_ino != st1.st_ino ||
st2.st_uid != st1.st_uid ||
st2.st_nlink != 1) {
printf("ERROR: Unable to verify file %s\n", file);
fclose(fp);
return NULL;
}
return fp;
}

View File

@ -40,6 +40,7 @@
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_bmc.h>
extern int verbose;
@ -95,10 +96,276 @@ static int ipmi_bmc_reset(struct ipmi_intf * intf, int cmd)
return 0;
}
struct bmc_enables_data {
#if WORDS_BIGENDIAN
unsigned char oem2 : 1;
unsigned char oem1 : 1;
unsigned char oem0 : 1;
unsigned char __reserved : 1;
unsigned char system_event_log : 1;
unsigned char event_msgbuf : 1;
unsigned char event_msgbuf_intr : 1;
unsigned char receive_msg_intr : 1;
#else
unsigned char receive_msg_intr : 1;
unsigned char event_msgbuf_intr : 1;
unsigned char event_msgbuf : 1;
unsigned char system_event_log : 1;
unsigned char __reserved : 1;
unsigned char oem0 : 1;
unsigned char oem1 : 1;
unsigned char oem2 : 1;
#endif
} __attribute__ ((packed));
struct bitfield_data {
const char * name;
const char * desc;
uint32_t mask;
int write;
};
struct bitfield_data bmc_enables_bf[] = {
{
name: "recv_msg_intr",
desc: "Receive Message Queue Interrupt",
mask: 1<<0,
write: 1,
},
{
name: "event_msg_intr",
desc: "Event Message Buffer Full Interrupt",
mask: 1<<1,
write: 1,
},
{
name: "event_msg",
desc: "Event Message Buffer",
mask: 1<<2,
write: 1,
},
{
name: "system_event_log",
desc: "System Event Logging",
mask: 1<<3,
write: 1,
},
{
name: "oem0",
desc: "OEM 0",
mask: 1<<5,
write: 1,
},
{
name: "oem1",
desc: "OEM 1",
mask: 1<<6,
write: 1,
},
{
name: "oem2",
desc: "OEM 2",
mask: 1<<7,
write: 1,
},
{ NULL },
};
static void printf_bmc_usage()
{
struct bitfield_data * bf;
printf("BMC Commands:\n");
printf(" reset <warm|cold>\n");
printf(" info\n");
printf(" getenables\n");
printf(" setenables <option=on|off> ...\n");
for (bf = bmc_enables_bf; bf->name; bf++) {
if (!bf->write)
continue;
printf(" %-20s %s\n", bf->name, bf->desc);
}
}
static int ipmi_bmc_get_enables(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct bitfield_data * bf;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = BMC_GET_GLOBAL_ENABLES;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf("Error in BMC Get Global Enables Command\n");
return -1;
}
if (rsp->ccode) {
printf("BMC Get Global Enables command failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
for (bf = bmc_enables_bf; bf->name; bf++) {
printf("%-40s : %sabled\n", bf->desc,
rsp->data[0] & bf->mask ? "en" : "dis");
}
return 0;
}
static int ipmi_bmc_set_enables(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct bitfield_data * bf;
unsigned char en;
int i;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
if (argc < 1 || !strncmp(argv[0], "help", 4)) {
printf_bmc_usage();
return 0;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = BMC_GET_GLOBAL_ENABLES;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf("Error in BMC Get Global Enables Command\n");
return -1;
}
if (rsp->ccode) {
printf("BMC Get Global Enables command failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
en = rsp->data[0];
for (i = 0; i < argc; i++) {
for (bf = bmc_enables_bf; bf->name; bf++) {
int nl = strlen(bf->name);
if (!strncmp(argv[i], bf->name, nl)) {
if (!strncmp(argv[i]+nl+1, "off", 3)) {
printf("Disabling %s\n", bf->desc);
en &= ~bf->mask;
}
else if (!strncmp(argv[i]+nl+1, "on", 2)) {
printf("Enabling %s\n", bf->desc);
en |= bf->mask;
}
else {
printf("Unrecognized option: %s\n", argv[i]);
}
}
}
}
if (en == rsp->data[0]) {
printf("\nNothing to change...\n");
ipmi_bmc_get_enables(intf);
return 0;
}
req.msg.cmd = BMC_SET_GLOBAL_ENABLES;
req.msg.data = &en;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp)
printf("Error in BMC Set Global Enables Command\n");
else if (rsp->ccode)
printf("BMC Set Global Enables command failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
else {
printf("\nVerifying...\n");
ipmi_bmc_get_enables(intf);
}
return 0;
}
/* IPM Device, Get Device ID Command - Additional Device Support */
const char *ipm_dev_adtl_dev_support[8] = {
"Sensor Device", /* bit 0 */
"SDR Repository Device", /* bit 1 */
"SEL Device", /* bit 2 */
"FRU Inventory Device", /* ... */
"IPMB Event Receiver",
"IPMB Event Generator",
"Bridge",
"Chassis Device" /* bit 7 */
};
static int ipmi_bmc_get_deviceid(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct ipm_devid_rsp *devid;
int i;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = BMC_GET_DEVICE_ID;
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf("Error in BMC Get Device ID Command\n");
return -1;
}
if (rsp->ccode) {
printf("BMC Get Device ID returned %x\n", rsp->ccode);
return -1;
}
devid = (struct ipm_devid_rsp *) rsp->data;
printf("Device ID : %i\n",
devid->device_id);
printf("Device Revision : %i\n",
devid->device_revision & IPM_DEV_DEVICE_ID_REV_MASK);
printf("Firmware Revision : %u.%x\n",
devid->fw_rev1 & IPM_DEV_FWREV1_MAJOR_MASK,
devid->fw_rev2);
printf("IPMI Version : %x.%x\n",
IPM_DEV_IPMI_VERSION_MAJOR(devid->ipmi_version),
IPM_DEV_IPMI_VERSION_MINOR(devid->ipmi_version));
printf("Manufacturer ID : %lu\n",
(long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id));
printf("Product ID : %u (0x%02x%02x)\n",
buf2short((unsigned char *)(devid->product_id)),
devid->product_id[1], devid->product_id[0]);
printf("Device Available : %s\n",
(devid->fw_rev1 & IPM_DEV_FWREV1_AVAIL_MASK) ?
"no" : "yes");
printf("Provides Device SDRs : %s\n",
(devid->device_revision & IPM_DEV_DEVICE_ID_SDR_MASK) ?
"yes" : "no");
printf("Additional Device Support :\n");
for (i = 0; i < IPM_DEV_ADTL_SUPPORT_BITS; i++) {
if (devid->adtl_device_support & (1 << i)) {
printf(" %s\n", ipm_dev_adtl_dev_support[i]);
}
}
printf("Aux Firmware Rev Info : \n");
/* These values could be looked-up by vendor if documented,
* so we put them on individual lines for better treatment later
*/
printf(" 0x%02x\n 0x%02x\n 0x%02x\n 0x%02x\n",
devid->aux_fw_rev[0], devid->aux_fw_rev[1],
devid->aux_fw_rev[2], devid->aux_fw_rev[3]);
return 0;
}
int ipmi_bmc_main(struct ipmi_intf * intf, int argc, char ** argv)
{
if (!argc || !strncmp(argv[0], "help", 4)) {
printf("BMC Commands: reset\n");
printf_bmc_usage();
return 0;
}
else if (!strncmp(argv[0], "reset", 5)) {
@ -115,5 +382,14 @@ int ipmi_bmc_main(struct ipmi_intf * intf, int argc, char ** argv)
printf("reset commands: warm, cold\n");
}
}
else if (!strncmp(argv[0], "info", 4)) {
ipmi_bmc_get_deviceid(intf);
}
else if (!strncmp(argv[0], "getenables", 7)) {
ipmi_bmc_get_enables(intf);
}
else if (!strncmp(argv[0], "setenables", 7)) {
ipmi_bmc_set_enables(intf, argc-1, &(argv[1]));
}
return 0;
}

604
ipmitool/lib/ipmi_channel.c Normal file
View File

@ -0,0 +1,604 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_channel.h>
#include <ipmitool/ipmi_constants.h>
void printf_channel_usage (void);
extern const struct valstr ipmi_authtype_vals[];
static const struct valstr ipmi_channel_protocol_vals[] = {
{ 0x00, "reserved" },
{ 0x01, "IPMB-1.0" },
{ 0x02, "ICMB-1.0" },
{ 0x03, "reserved" },
{ 0x04, "IPMI-SMBus" },
{ 0x05, "KCS" },
{ 0x06, "SMIC" },
{ 0x07, "BT-10" },
{ 0x08, "BT-15" },
{ 0x09, "TMode" },
{ 0x1c, "OEM 1" },
{ 0x1d, "OEM 2" },
{ 0x1e, "OEM 3" },
{ 0x1f, "OEM 4" },
{ 0x00, NULL },
};
static const struct valstr ipmi_channel_medium_vals[] = {
{ 0x00, "reserved" },
{ 0x01, "IPMB (I2C)" },
{ 0x02, "ICMB v1.0" },
{ 0x03, "ICMB v0.9" },
{ 0x04, "802.3 LAN" },
{ 0x05, "Serial/Modem" },
{ 0x06, "Other LAN" },
{ 0x07, "PCI SMBus" },
{ 0x08, "SMBus v1.0/v1.1" },
{ 0x09, "SMBus v2.0" },
{ 0x0a, "USB 1.x" },
{ 0x0b, "USB 2.x" },
{ 0x0c, "System Interface" },
{ 0x00, NULL },
};
/**
* ipmi_1_5_authtypes
*
* Create a string describing the supported authentication types as
* specificed by the parameter n
*/
const char * ipmi_1_5_authtypes(unsigned char n)
{
unsigned int i;
static char supportedTypes[128];
bzero(supportedTypes, 128);
i = 0;
while (ipmi_authtype_vals[i].val)
{
if (n & ipmi_authtype_vals[i].val)
{
strcat(supportedTypes, ipmi_authtype_vals[i].str);
strcat(supportedTypes, " ");
}
++i;
}
return supportedTypes;
}
/**
* ipmi_get_channel_auth_cap
*
* return 0 on success
* -1 on failure
*/
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
unsigned char channel,
unsigned char priv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct get_channel_auth_cap_rsp auth_cap;
unsigned char msg_data[2];
msg_data[0] = channel | 0x80; // Ask for IPMI v2 data as well
msg_data[1] = priv;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
req.msg.data = msg_data;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
/*
* It's very possible that this failed because we asked for IPMI v2 data
* Ask again, without requesting IPMI v2 data
*/
msg_data[0] &= 0x7F;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get Channel Authentication Capabilities Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
}
memcpy(&auth_cap, rsp->data, sizeof(struct get_channel_auth_cap_rsp));
printf("Channel number : %d\n",
auth_cap.channel_number);
printf("IPMI v1.5 auth types : %s\n",
ipmi_1_5_authtypes(auth_cap.enabled_auth_types));
if (auth_cap.v20_data_available)
printf("KG status : %s\n",
(auth_cap.kg_status) ? "non-zero" : "default (all zeroes)");
printf("Per message authentication : %sabled\n",
(auth_cap.per_message_auth) ? "en" : "dis");
printf("User level authentication : %sabled\n",
(auth_cap.user_level_auth) ? "en" : "dis");
printf("Non-null user names exist : %s\n",
(auth_cap.non_null_usernames) ? "yes" : "no");
printf("Null user names exist : %s\n",
(auth_cap.null_usernames) ? "yes" : "no");
printf("Anonymous login enabled : %s\n",
(auth_cap.anon_login_enabled) ? "yes" : "no");
if (auth_cap.v20_data_available)
{
printf("Channel supports IPMI v1.5 : %s\n",
(auth_cap.ipmiv15_support) ? "yes" : "no");
printf("Channel supports IPMI v2.0 : %s\n",
(auth_cap.ipmiv20_support) ? "yes" : "no");
}
/*
* If there is support for an OEM authentication type, there is some
* information.
*/
if (auth_cap.enabled_auth_types & IPMI_1_5_AUTH_TYPE_BIT_OEM)
{
printf("IANA Number for OEM : %d\n",
auth_cap.oem_id[0] |
auth_cap.oem_id[1] << 8 |
auth_cap.oem_id[2] << 16);
printf("OEM Auxiliary Data : 0x%x\n",
auth_cap.oem_aux_data);
}
return 0;
}
/**
* ipmi_get_channel_info
*
* returns 0 on success
* -1 on failure
*
*/
int
ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[2];
struct get_channel_info_rsp channel_info;
struct get_channel_access_rsp channel_access;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_INFO; // 0x42
req.msg.data = &channel;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get Channel Info Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp));
printf("Channel 0x%x info:\n", channel_info.channel_number);
printf(" Channel Medium Type : %s\n",
val2str(channel_info.channel_medium, ipmi_channel_medium_vals));
printf(" Channel Protocol Type : %s\n",
val2str(channel_info.channel_protocol, ipmi_channel_protocol_vals));
printf(" Session Support : ");
switch (channel_info.session_support) {
case 0x00:
printf("session-less\n");
break;
case 0x40:
printf("single-session\n");
break;
case 0x80:
printf("multi-session\n");
break;
case 0xc0:
default:
printf("session-based\n");
break;
}
printf(" Active Session Count : %d\n",
channel_info.active_sessions);
printf(" Protocol Vendor ID : %d\n",
channel_info.vendor_id[0] |
channel_info.vendor_id[1] << 8 |
channel_info.vendor_id[2] << 16);
memset(&req, 0, sizeof(req));
rqdata[0] = channel & 0xf;
/* get volatile settings */
rqdata[1] = 0x80; /* 0x80=active */
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; // 0x41
req.msg.data = rqdata;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
return -1;
}
memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
printf(" Volatile(active) Settings\n");
printf(" Alerting : %sabled\n",
(channel_access.alerting) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n",
(channel_access.per_message_auth) ? "dis" : "en");
printf(" User Level Auth : %sabled\n",
(channel_access.user_level_auth) ? "dis" : "en");
printf(" Access Mode : ");
switch (channel_access.access_mode) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
/* get non-volatile settings */
rqdata[1] = 0x40; /* 0x40=non-volatile */
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
return -1;
}
memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
printf(" Non-Volatile Settings\n");
printf(" Alerting : %sabled\n",
(channel_access.alerting) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n",
(channel_access.per_message_auth) ? "dis" : "en");
printf(" User Level Auth : %sabled\n",
(channel_access.user_level_auth) ? "dis" : "en");
printf(" Access Mode : ");
switch (channel_access.access_mode) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
return 0;
}
static int
ipmi_get_user_access(struct ipmi_intf * intf, unsigned char channel, unsigned char userid)
{
struct ipmi_rs * rsp;
struct ipmi_rq req1, req2;
unsigned char rqdata[2];
struct get_user_access_rsp user_access;
int curr_uid, max_uid = 0, init = 1;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
curr_uid = userid ? userid : 1;
memset(&req1, 0, sizeof(req1));
req1.msg.netfn = IPMI_NETFN_APP;
req1.msg.cmd = IPMI_GET_USER_ACCESS;
req1.msg.data = rqdata;
req1.msg.data_len = 2;
memset(&req2, 0, sizeof(req2));
req2.msg.netfn = IPMI_NETFN_APP;
req2.msg.cmd = IPMI_GET_USER_NAME;
req2.msg.data = rqdata;
req2.msg.data_len = 1;
do
{
rqdata[0] = channel & 0xf;
rqdata[1] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req1);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
rqdata[0] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req2);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Name Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
}
if (init)
{
printf("Maximum User IDs : %d\n", user_access.max_user_ids);
printf("Enabled User IDs : %d\n", user_access.enabled_user_ids);
max_uid = user_access.max_user_ids;
init = 0;
}
printf("\nUser ID : %d\n", curr_uid);
printf("User Name : %s\n", rsp->data);
printf("Fixed Name : %s\n", curr_uid <= user_access.fixed_user_ids ? "Yes" : "No");
printf("Access Available : %s\n", user_access.callin_callback ? "callback" : "call-in / callback");
printf("Link Authentication : %sabled\n", user_access.link_auth ? "en" : "dis");
printf("IPMI Messaging : %sabled\n", user_access.ipmi_messaging ? "en" : "dis");
printf("Privilege Level : %s\n", val2str(user_access.privilege_limit, ipmi_privlvl_vals));
curr_uid ++;
} while (!userid && curr_uid <= max_uid);
return 0;
}
static void
ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv)
{
unsigned char channel, userid;
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[2];
struct get_user_access_rsp user_access;
struct set_user_access_data set_access;
int i;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
if (argc < 3 || !strncmp(argv[0], "help", 4)) {
printf_channel_usage();
return;
}
channel = (unsigned char)strtol(argv[0], NULL, 0);
userid = (unsigned char)strtol(argv[1], NULL, 0);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_USER_ACCESS;
req.msg.data = rqdata;
req.msg.data_len = 2;
rqdata[0] = channel & 0xf;
rqdata[1] = userid & 0x3f;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
set_access.change_bits = 1;
set_access.callin_callback = user_access.callin_callback;
set_access.link_auth = user_access.link_auth;
set_access.ipmi_messaging = user_access.ipmi_messaging;
set_access.channel = channel;
set_access.user_id = userid;
set_access.privilege_limit = user_access.privilege_limit;
set_access.session_limit = 0;
for (i = 2; i < argc; i ++)
{
if (!strncmp(argv[i], "callin=", 7)) {
set_access.callin_callback = !strncmp (argv[i]+7, "off", 3);
}
else if (!strncmp(argv[i], "link=", 5)) {
set_access.link_auth = strncmp (argv[i]+5, "off", 3);
}
else if (!strncmp(argv[i], "ipmi=", 5)) {
set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3);
}
else if (!strncmp(argv[i], "privilege=", 10)) {
set_access.privilege_limit = strtol (argv[i]+10, NULL, 0);
}
else {
printf ("Invalid option: %s\n", argv [i]);
return;
}
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_SET_USER_ACCESS;
req.msg.data = (unsigned char *) &set_access;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Set User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return;
}
return;
}
void
printf_channel_usage()
{
printf("Channel Commands: authcap <channel number> <max privilege>\n");
printf(" getaccess <channel number> [user id]\n");
printf(" setaccess <channel number> <user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]\n");
printf(" info [channel number]\n");
printf("\n");
printf("Possible privilege levels are:\n");
printf(" 1 Callback level\n");
printf(" 2 User level\n");
printf(" 3 Operator level\n");
printf(" 4 Administrator level\n");
printf(" 5 OEM Proprietary level\n");
printf(" 15 No access\n");
}
int
ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
if (!argc || !strncmp(argv[0], "help", 4))
{
printf_channel_usage();
}
else if (!strncmp(argv[0], "authcap", 7))
{
if (argc != 3)
printf_channel_usage();
else
retval = ipmi_get_channel_auth_cap(intf,
(unsigned char)strtol(argv[1], NULL, 0),
(unsigned char)strtol(argv[2], NULL, 0));
}
else if (!strncmp(argv[0], "getaccess", 10))
{
if (argc < 2 || argc > 3)
printf_channel_usage();
else {
unsigned char ch = (unsigned char)strtol(argv[1], NULL, 0);
unsigned char id = 0;
if (argc == 3)
id = (unsigned char)strtol(argv[2], NULL, 0);
retval = ipmi_get_user_access(intf, ch, id);
}
}
else if (!strncmp(argv[0], "setaccess", 9))
{
ipmi_set_user_access(intf, argc-1, &(argv[1]));
}
else if (!strncmp(argv[0], "info", 4))
{
if (argc > 2)
printf_channel_usage();
else {
unsigned char ch = 0xe;
if (argc == 2)
ch = (unsigned char)strtol(argv[1], NULL, 0);
retval = ipmi_get_channel_info(intf, ch);
}
}
else
{
printf("Invalid CHANNEL command: %s\n", argv[0]);
printf_channel_usage();
retval = 1;
}
return retval;
}

View File

@ -40,6 +40,7 @@
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_chassis.h>
extern int verbose;
@ -77,57 +78,90 @@ static const struct valstr ipmi_chassis_power_control_vals[] = {
static void ipmi_chassis_power_control(struct ipmi_intf * intf, unsigned char ctl)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_CHASSIS;
req.msg.cmd = 0x2;
req.msg.data = &ctl;
req.msg.data_len = 1;
printf("Chassis Power Control: %s\n",
val2str(ctl, ipmi_chassis_power_control_vals));
rsp = intf->sendrecv(intf, &req);
intf->sendrecv(intf, &req);
intf->abort = 1;
if (!rsp || rsp->ccode) {
printf("Unable to set Chassis Power Control to %s\n",
val2str(ctl, ipmi_chassis_power_control_vals));
} else {
printf("Chassis Power Control: %s\n",
val2str(ctl, ipmi_chassis_power_control_vals));
intf->abort = 1;
}
}
static void ipmi_chassis_identify(struct ipmi_intf * intf, char * arg)
{
struct ipmi_rq req;
struct ipmi_rs * rsp;
struct {
unsigned char interval;
unsigned char force_on;
} identify_data;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_CHASSIS;
req.msg.cmd = 0x4;
printf("Chassis identify interval: ");
if (arg) {
struct {
unsigned char interval;
unsigned char force_on;
} identify_data;
if (!strcmp(arg, "force")){
identify_data.interval = 0;
identify_data.force_on = 1;
printf("indefinite\n");
} else {
identify_data.interval = (unsigned char)atoi(arg);
identify_data.force_on = 0;
if (identify_data.interval)
printf("%d seconds\n", identify_data.interval);
else
printf("off\n");
}
req.msg.data = (unsigned char *)&identify_data;
req.msg.data_len = 2;
} else {
printf("default (15 seconds)\n");
/* The Force Identify On byte is optional and not
* supported by all devices-- if force is not specified,
* we pass only one data byte; if specified, we pass two
* data bytes and check for an error completion code
*/
req.msg.data_len = (identify_data.force_on) ? 2 : 1;
}
intf->sendrecv(intf, &req);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("ERROR:%x Chassis Identify Command\n", rsp->ccode);
if (identify_data.force_on) {
/* Intel SE7501WV2 F/W 1.2 returns CC 0xC7, but
* the IPMI v1.5 spec does not standardize a CC
* if unsupported, so we warn
*/
printf("Chassis may not support Force Identify On\n");
}
return;
}
printf("Chassis identify interval: ");
if (!arg) {
printf("default (15 seconds)\n");
} else {
if (identify_data.force_on) {
printf("indefinate\n");
} else {
if (identify_data.interval) {
printf("%i seconds\n", identify_data.interval);
} else {
printf("off\n");
}
}
}
}
static void ipmi_chassis_poh(struct ipmi_intf * intf)
@ -148,7 +182,7 @@ static void ipmi_chassis_poh(struct ipmi_intf * intf)
memcpy(&count, rsp->data+1, 4);
printf("POH Counter : %li hours total (%li days, %li hours)\n",
count, (uint32_t)(count / 24), (uint32_t)(count % 24));
(long)count, (long)(count / 24), (long)(count % 24));
}
static void ipmi_chassis_restart_cause(struct ipmi_intf * intf)
@ -282,6 +316,8 @@ static void ipmi_chassis_set_bootparam(struct ipmi_intf * intf, unsigned char pa
struct ipmi_rq req;
unsigned char msg_data[16];
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
memset(msg_data, 0, 16);
msg_data[0] = param & 0x7f;
memcpy(msg_data+1, data, len);
@ -339,6 +375,8 @@ static void ipmi_chassis_set_bootflag(struct ipmi_intf * intf, char * arg)
{
unsigned char flags[5];
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
if (!arg) {
printf("Error: no bootflag argument supplied\n");
return;
@ -376,8 +414,7 @@ static void ipmi_chassis_power_policy(struct ipmi_intf * intf, unsigned char pol
struct ipmi_rs * rsp;
struct ipmi_rq req;
if (!policy)
return;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_CHASSIS;
@ -386,8 +423,14 @@ static void ipmi_chassis_power_policy(struct ipmi_intf * intf, unsigned char pol
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
if (!rsp)
return;
if (rsp->ccode > 0) {
printf("BMC Power Restore Policy command failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
return;
}
if (policy == IPMI_CHASSIS_POLICY_NO_CHANGE) {
printf("Supported chassis power policy: ");

136
ipmitool/lib/ipmi_event.c Normal file
View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_sel.h>
static int
ipmi_send_platform_event(struct ipmi_intf * intf, int num)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[8];
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
memset(&req, 0, sizeof(req));
memset(rqdata, 0, 8);
printf("Sending ");
/* IPMB/LAN/etc */
switch (num) {
case 1: /* temperature */
printf("Temperature - Upper Critical - Going High");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x01; /* Sensor Type */
rqdata[2] = 0x30; /* Sensor # */
rqdata[3] = 0x01; /* Event Dir / Event Type */
rqdata[4] = 0x59; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
case 2: /* voltage error */
printf("Voltage Threshold - Lower Critical - Going Low");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x02; /* Sensor Type */
rqdata[2] = 0x60; /* Sensor # */
rqdata[3] = 0x01; /* Event Dir / Event Type */
rqdata[4] = 0x52; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
case 3: /* correctable ECC */
printf("Memory - Correctable ECC");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x0c; /* Sensor Type */
rqdata[2] = 0x01; /* Sensor # */
rqdata[3] = 0x6f; /* Event Dir / Event Type */
rqdata[4] = 0x00; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
default:
printf("Invalid event number: %d\n", num);
return -1;
}
printf(" event to BMC\n");
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = 0x02;
req.msg.data = rqdata;
req.msg.data_len = 7;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Platform Event Message Command\n", rsp?rsp->ccode:0);
return -1;
}
return 0;
}
int ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv)
{
unsigned char c;
if (!argc || !strncmp(argv[0], "help", 4)) {
printf("usage: event <num>\n");
printf(" 1 : Temperature - Upper Critical - Going High\n");
printf(" 2 : Voltage Threshold - Lower Critical - Going Low\n");
printf(" 3 : Memory - Correctable ECC\n");
} else {
c = (unsigned char)strtol(argv[0], NULL, 0);
ipmi_send_platform_event(intf, c);
}
return 0;
}

View File

@ -35,6 +35,7 @@
*/
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_fru.h>
#include <ipmitool/ipmi_sdr.h>
@ -50,32 +51,141 @@ extern void ipmi_spd_print(struct ipmi_intf * intf, unsigned char id);
static char * get_fru_area_str(unsigned char * data, int * offset)
{
static const char bcd_plus[] = "0123456789 -.:,_";
char * str;
int len;
int len, size=0, i, j, k;
int off = *offset;
union {
uint32_t bits;
char chars[4];
} u;
k = ((data[off] & 0xC0) >> 6); /* bits 6,7 contain format */
len = data[off++];
len &= 0x3f; /* bits 0:5 contain length */
len &= 0x3f; /* bits 0:5 contain length */
str = malloc(len+1);
switch(k) {
case 0: /* 0: binary/unspecified */
size = (len*2); /* (hex dump -> 2x length) */
break;
case 2: /* 2: 6-bit ASCII */
size = ((((len+2)*4)/3) & ~3);/* (4 chars per group of 1-3 bytes) */
break;
case 3: /* 3: 8-bit ASCII */
case 1: /* 1: BCD plus */
size = len; /* (no length adjustment) */
}
str = malloc(size+1);
if (!str)
return NULL;
str[len] = '\0';
memcpy(str, &data[off], len);
if (len == 0)
str[0] = '\0';
else {
switch(k) {
case 0:
strcpy(str, buf2str(&data[off], len));
break;
case 1:
for (k=0; k<len; k++)
str[k] = bcd_plus[(data[off+k] & 0x0f)];
str[k] = '\0';
break;
case 2:
for (i=j=0; i<len; i+=3) {
u.bits = 0;
k = ((len-i) < 3 ? (len-i) : 3);
#if WORDS_BIGENDIAN
u.chars[3] = data[off+i];
u.chars[2] = (k > 1 ? data[off+i+1] : 0);
u.chars[1] = (k > 2 ? data[off+i+2] : 0);
#define CHAR_IDX 3
#else
memcpy((void *)&u.bits, &data[off+i], k);
#define CHAR_IDX 0
#endif
for (k=0; k<4; k++) {
str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20);
u.bits >>= 6;
}
}
str[j] = '\0';
break;
case 3:
memcpy(str, &data[off], len);
str[len] = '\0';
}
off += len;
}
off += len;
*offset = off;
return str;
}
static int
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, unsigned char id,
unsigned int offset, unsigned int length, unsigned char *frubuf)
{ /*
// fill in frubuf[offset:length] from the FRU[offset:length]
// rc=1 on success
*/
static unsigned int fru_data_rqst_size = 32;
unsigned int off = offset, tmp, finish;
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char msg_data[4];
finish = offset + length;
if (finish > fru->size)
return -1;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_FRU_DATA;
req.msg.data = msg_data;
req.msg.data_len = 4;
if (fru->access && fru_data_rqst_size > 16)
fru_data_rqst_size = 16;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
msg_data[1] = (unsigned char)tmp;
msg_data[2] = (unsigned char)(tmp >> 8);
tmp = finish - off;
if (tmp > fru_data_rqst_size)
msg_data[3] = (unsigned char)fru_data_rqst_size;
else
msg_data[3] = (unsigned char)tmp;
rsp = intf->sendrecv(intf, &req);
if (!rsp)
break;
if ((rsp->ccode==0xc7 || rsp->ccode==0xc8) && --fru_data_rqst_size > 8)
continue;
if (rsp->ccode)
break;
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
memcpy((frubuf + off), rsp->data + 1, tmp);
off += tmp;
} while (off < finish);
return (off >= finish);
}
static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char fru_data[256], msg_data[4];
int i, len, offset;
unsigned char * fru_data;
unsigned char msg_data[4];
int i, len;
struct fru_area_chassis chassis;
struct fru_area_board board;
@ -83,6 +193,15 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
struct fru_info fru;
struct fru_header header;
enum {
OFF_INTERNAL
, OFF_CHASSIS
, OFF_BOARD
, OFF_PRODUCT
, OFF_MULTI
, OFF_COUNT /* must be last */
};
unsigned int area_offsets[OFF_COUNT];
msg_data[0] = id;
@ -93,14 +212,23 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
if (!rsp)
return;
if(rsp->ccode)
{
if (rsp->ccode == 0xc3)
printf (" Timeout accessing FRU info. (Device not present?)\n");
return;
}
fru.size = (rsp->data[1] << 8) | rsp->data[0];
fru.access = rsp->data[2] & 0x1;
if (verbose > 1)
printf("fru.size = %d bytes (accessed by %s)\n",
fru.size, fru.access ? "words" : "bytes");
if (!fru.size)
return;
msg_data[0] = id;
msg_data[1] = 0;
@ -136,151 +264,160 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
return;
}
header.offset.internal *= 8;
header.offset.chassis *= 8;
header.offset.board *= 8;
header.offset.product *= 8;
header.offset.multi *= 8;
area_offsets[OFF_INTERNAL] = 8 * header.offset.internal;
area_offsets[OFF_CHASSIS] = 8 * header.offset.chassis;
area_offsets[OFF_BOARD] = 8 * header.offset.board;
area_offsets[OFF_PRODUCT] = 8 * header.offset.product;
area_offsets[OFF_MULTI] = 8 * header.offset.multi;
if (verbose > 1) {
printf("fru.header.version: 0x%x\n", header.version);
printf("fru.header.offset.internal: 0x%x\n", header.offset.internal);
printf("fru.header.offset.chassis: 0x%x\n", header.offset.chassis);
printf("fru.header.offset.board: 0x%x\n", header.offset.board);
printf("fru.header.offset.product: 0x%x\n", header.offset.product);
printf("fru.header.offset.multi: 0x%x\n", header.offset.multi);
printf("fru.header.offset.internal: 0x%x\n", area_offsets[OFF_INTERNAL]);
printf("fru.header.offset.chassis: 0x%x\n", area_offsets[OFF_CHASSIS]);
printf("fru.header.offset.board: 0x%x\n", area_offsets[OFF_BOARD]);
printf("fru.header.offset.product: 0x%x\n", area_offsets[OFF_PRODUCT]);
printf("fru.header.offset.multi: 0x%x\n", area_offsets[OFF_MULTI]);
}
offset = 0;
memset(fru_data, 0, 256);
do {
msg_data[0] = id;
msg_data[1] = offset;
msg_data[2] = 0;
msg_data[3] = (fru.size - offset) > 32 ? 32 : (fru.size - offset);
fru_data = malloc(fru.size+1);
if (!fru_data)
return;
memset(fru_data, 0, fru.size+1);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
break;
len = rsp->data[0];
memcpy(&fru_data[offset], rsp->data + 1, len);
offset += len;
} while (offset < fru.size);
/* rather than reading the entire part, only read the areas we'll format */
/* chassis area */
if (header.offset.chassis)
if (area_offsets[OFF_CHASSIS] >= sizeof(struct fru_header))
{
i = header.offset.chassis;
chassis.area_ver = fru_data[i++];
chassis.area_len = fru_data[i++] * 8;
chassis.type = fru_data[i++];
chassis.part = get_fru_area_str(fru_data, &i);
chassis.serial = get_fru_area_str(fru_data, &i);
printf(" Chassis Type : %s\n", chassis_type_desc[chassis.type]);
printf(" Chassis Part : %s\n", chassis.part);
printf(" Chassis Serial : %s\n", chassis.serial);
while (fru_data[i] != 0xc1 && i < header.offset.chassis + chassis.area_len)
i = area_offsets[OFF_CHASSIS];
read_fru_area(intf, &fru, id, i, 2, fru_data);
chassis.area_len = 8 * fru_data[i+1];
if (chassis.area_len > 0
&& read_fru_area(intf, &fru, id, i, chassis.area_len, fru_data) > 0)
{
char *extra;
chassis.area_ver = fru_data[i++];
chassis.area_len = fru_data[i++] * 8;
chassis.type = fru_data[i++];
chassis.part = get_fru_area_str(fru_data, &i);
chassis.serial = get_fru_area_str(fru_data, &i);
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Chassis Extra : %s\n", extra);
free(extra);
printf(" Chassis Type : %s\n", chassis_type_desc[chassis.type]);
printf(" Chassis Part : %s\n", chassis.part);
printf(" Chassis Serial : %s\n", chassis.serial);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_CHASSIS] + chassis.area_len)
{
char *extra;
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Chassis Extra : %s\n", extra);
free(extra);
}
free(chassis.part);
free(chassis.serial);
}
free(chassis.part);
free(chassis.serial);
}
/* board area */
if (header.offset.board)
if (area_offsets[OFF_BOARD] >= sizeof(struct fru_header))
{
i = header.offset.board;
board.area_ver = fru_data[i++];
board.area_len = fru_data[i++] * 8;
board.lang = fru_data[i++];
i += 3; /* skip mfg. date time */
board.mfg = get_fru_area_str(fru_data, &i);
board.prod = get_fru_area_str(fru_data, &i);
board.serial = get_fru_area_str(fru_data, &i);
board.part = get_fru_area_str(fru_data, &i);
board.fru = get_fru_area_str(fru_data, &i);
printf(" Board Mfg : %s\n", board.mfg);
printf(" Board Product : %s\n", board.prod);
printf(" Board Serial : %s\n", board.serial);
printf(" Board Part : %s\n", board.part);
if (verbose > 0)
printf(" Board FRU ID : %s\n", board.fru);
while (fru_data[i] != 0xc1 && i < header.offset.board + board.area_len)
i = area_offsets[OFF_BOARD];
read_fru_area(intf, &fru, id, i, 2, fru_data);
board.area_len = 8 * fru_data[i+1];
if (board.area_len > 0
&& read_fru_area(intf, &fru, id, i, board.area_len, fru_data) > 0)
{
char *extra;
board.area_ver = fru_data[i++];
board.area_len = fru_data[i++] * 8;
board.lang = fru_data[i++];
i += 3; /* skip mfg. date time */
board.mfg = get_fru_area_str(fru_data, &i);
board.prod = get_fru_area_str(fru_data, &i);
board.serial = get_fru_area_str(fru_data, &i);
board.part = get_fru_area_str(fru_data, &i);
board.fru = get_fru_area_str(fru_data, &i);
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Board Extra : %s\n", extra);
free(extra);
printf(" Board Mfg : %s\n", board.mfg);
printf(" Board Product : %s\n", board.prod);
printf(" Board Serial : %s\n", board.serial);
printf(" Board Part : %s\n", board.part);
if (verbose > 0)
printf(" Board FRU ID : %s\n", board.fru);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_BOARD] + board.area_len)
{
char *extra;
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Board Extra : %s\n", extra);
free(extra);
}
free(board.mfg);
free(board.prod);
free(board.serial);
free(board.part);
free(board.fru);
}
free(board.mfg);
free(board.prod);
free(board.serial);
free(board.part);
free(board.fru);
}
/* product area */
if (header.offset.product)
if (area_offsets[OFF_PRODUCT] >= sizeof(struct fru_header))
{
i = header.offset.product;
product.area_ver = fru_data[i++];
product.area_len = fru_data[i++] * 8;
product.lang = fru_data[i++];
product.mfg = get_fru_area_str(fru_data, &i);
product.name = get_fru_area_str(fru_data, &i);
product.part = get_fru_area_str(fru_data, &i);
product.version = get_fru_area_str(fru_data, &i);
product.serial = get_fru_area_str(fru_data, &i);
product.asset = get_fru_area_str(fru_data, &i);
product.fru = get_fru_area_str(fru_data, &i);
printf(" Product Mfg : %s\n", product.mfg);
printf(" Product Name : %s\n", product.name);
printf(" Product Part : %s\n", product.part);
printf(" Product Version : %s\n", product.version);
printf(" Product Serial : %s\n", product.serial);
printf(" Product Asset : %s\n", product.asset);
if (verbose > 0)
printf(" Product FRU ID : %s\n", product.fru);
while (fru_data[i] != 0xc1 && i < header.offset.product + product.area_len)
i = area_offsets[OFF_PRODUCT];
read_fru_area(intf, &fru, id, i, 2, fru_data);
product.area_len = 8 * fru_data[i+1];
if (product.area_len > 0
&& read_fru_area(intf, &fru, id, i, product.area_len, fru_data) > 0)
{
char *extra;
product.area_ver = fru_data[i++];
product.area_len = fru_data[i++] * 8;
product.lang = fru_data[i++];
product.mfg = get_fru_area_str(fru_data, &i);
product.name = get_fru_area_str(fru_data, &i);
product.part = get_fru_area_str(fru_data, &i);
product.version = get_fru_area_str(fru_data, &i);
product.serial = get_fru_area_str(fru_data, &i);
product.asset = get_fru_area_str(fru_data, &i);
product.fru = get_fru_area_str(fru_data, &i);
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Product Extra : %s\n", extra);
free(extra);
printf(" Product Mfg : %s\n", product.mfg);
printf(" Product Name : %s\n", product.name);
printf(" Product Part : %s\n", product.part);
printf(" Product Version : %s\n", product.version);
printf(" Product Serial : %s\n", product.serial);
printf(" Product Asset : %s\n", product.asset);
if (verbose > 0)
printf(" Product FRU ID : %s\n", product.fru);
while (fru_data[i] != 0xc1 && i < area_offsets[OFF_PRODUCT] + product.area_len)
{
char *extra;
extra = get_fru_area_str(fru_data, &i);
if (extra [0]) printf(" Product Extra : %s\n", extra);
free(extra);
}
free(product.mfg);
free(product.name);
free(product.part);
free(product.version);
free(product.serial);
free(product.asset);
free(product.fru);
}
free(product.mfg);
free(product.name);
free(product.part);
free(product.version);
free(product.serial);
free(product.asset);
free(product.fru);
}
/* multirecord area */
if (header.offset.multi)
if (area_offsets[OFF_MULTI] >= sizeof(struct fru_header))
{
struct fru_multirec_header * h;
struct fru_multirec_powersupply * ps;
@ -288,13 +425,29 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
struct fru_multirec_dcload * dl;
unsigned short peak_capacity;
unsigned char peak_hold_up_time;
unsigned int last_off;
#define CHUNK_SIZE (255 + sizeof(struct fru_multirec_header))
i = header.offset.multi;
i = last_off = area_offsets[OFF_MULTI];
do
{
h = (struct fru_multirec_header *) (fru_data + i);
/* read multirec area in (at most) CHUNK_SIZE bytes at a time */
if (last_off < i+sizeof(*h) || last_off < i+h->len)
{
len = fru.size - last_off;
if (len > CHUNK_SIZE)
len = CHUNK_SIZE;
if (read_fru_area(intf, &fru, id, last_off, len, fru_data) > 0)
last_off += len;
else {
printf("ERROR: reading FRU data\n");
break;
}
}
switch (h->type)
{
case FRU_RECORD_TYPE_POWER_SUPPLY_INFORMATION:
@ -391,6 +544,8 @@ static void ipmi_fru_print(struct ipmi_intf * intf, unsigned char id)
i += h->len + sizeof (struct fru_multirec_header);
} while (!(h->format & 0x80));
}
free(fru_data);
}
static void ipmi_fru_print_all(struct ipmi_intf * intf)
@ -406,13 +561,17 @@ static void ipmi_fru_print_all(struct ipmi_intf * intf)
if (!(itr = ipmi_sdr_start(intf)))
return;
while (header = ipmi_sdr_get_next_header(intf, itr))
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL)
{
if (header->type != SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR)
continue;
fru = (struct sdr_record_fru_device_locator *) ipmi_sdr_get_record(intf, header, itr);
if (!fru || fru->device_type != 0x10)
if (!fru)
continue;
if (fru->device_type != 0x10
&& (fru->device_type_modifier != 0x02
|| fru->device_type < 0x08 || fru->device_type > 0x0f))
continue;
memset(desc, 0, sizeof(desc));
@ -423,7 +582,16 @@ static void ipmi_fru_print_all(struct ipmi_intf * intf)
switch (fru->device_type_modifier) {
case 0x00:
case 0x02:
ipmi_fru_print(intf, fru->keys.fru_device_id);
intf->target_addr = ((fru->keys.dev_access_addr << 1)
| (fru->keys.__reserved2 << 7));
if (intf->target_addr == IPMI_BMC_SLAVE_ADDR
&& fru->keys.fru_device_id == 0)
printf(" (Builtin FRU device)\n");
else {
ipmi_fru_print(intf, fru->keys.fru_device_id);
intf->target_addr = IPMI_BMC_SLAVE_ADDR;
}
break;
case 0x01:
ipmi_spd_print(intf, fru->keys.fru_device_id);

144
ipmitool/lib/ipmi_isol.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_isol.h>
extern int verbose;
static int ipmi_isol_setup(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char data[6];
/* TEST FOR AVAILABILITY */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_ENABLE_PARAM;
data[2] = ISOL_ENABLE_FLAG;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_ISOL;
req.msg.cmd = SET_ISOL_CONFIG;
req.msg.data = data;
req.msg.data_len = 3;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf("Error in Set ISOL Config Command\n");
return -1;
}
if (rsp->ccode == 0xc1) {
printf("Serial Over Lan not supported!\n");
return -1;
}
if (rsp->ccode) {
printf("Set Serial Over Lan Config returned %x\n", rsp->ccode);
return -1;
}
/* GET ISOL CONFIG */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_AUTHENTICATION_PARAM;
data[2] = 0x00; /* block */
data[3] = 0x00; /* selector */
req.msg.cmd = GET_ISOL_CONFIG;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x in Get ISOL Config command\n", rsp?rsp->ccode:0);
return -1;
}
if (verbose > 1)
printbuf(rsp->data, rsp->data_len, "ISOL Config");
/* SET ISOL CONFIG - AUTHENTICATION */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_AUTHENTICATION_PARAM;
data[2] = ISOL_PRIVILEGE_LEVEL_USER | (rsp->data[1] & 0x80);
req.msg.cmd = SET_ISOL_CONFIG;
req.msg.data_len = 3;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x in Set ISOL Config (Authentication) command\n", rsp?rsp->ccode:0);
return -1;
}
/* SET ISOL CONFIG - BAUD RATE */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_BAUD_RATE_PARAM;
data[2] = ISOL_PREFERRED_BAUD_RATE;
req.msg.cmd = SET_ISOL_CONFIG;
req.msg.data_len = 3;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x in Set ISOL Config (Baud Rate) command\n", rsp?rsp->ccode:0);
return -1;
}
return 0;
}
int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv)
{
if (!argc || !strncmp(argv[0], "help", 4)) {
printf("ISOL Commands: setup\n");
return 0;
}
else if (!strncmp(argv[0], "setup", 5)) {
ipmi_isol_setup(intf);
}
return 0;
}

View File

@ -48,65 +48,13 @@
#include <netdb.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_lanp.h>
extern int verbose;
extern struct ipmi_session lan_session;
const struct valstr ipmi_privlvl_vals[] = {
{ IPMI_SESSION_PRIV_CALLBACK, "CALLBACK" },
{ IPMI_SESSION_PRIV_USER, "USER" },
{ IPMI_SESSION_PRIV_OPERATOR, "OPERATOR" },
{ IPMI_SESSION_PRIV_ADMIN, "ADMINISTRATOR" },
{ IPMI_SESSION_PRIV_OEM, "OEM" },
{ 0xF, "NO ACCESS" },
{ 0, NULL },
};
const struct valstr ipmi_authtype_vals[] = {
{ IPMI_SESSION_AUTHTYPE_NONE, "NONE" },
{ IPMI_SESSION_AUTHTYPE_MD2, "MD2" },
{ IPMI_SESSION_AUTHTYPE_MD5, "MD5" },
{ IPMI_SESSION_AUTHTYPE_KEY, "PASSWORD" },
{ IPMI_SESSION_AUTHTYPE_OEM, "OEM" },
{ 0, NULL },
};
static const struct valstr ipmi_channel_protocol_vals[] = {
{ 0x00, "reserved" },
{ 0x01, "IPMB-1.0" },
{ 0x02, "ICMB-1.0" },
{ 0x03, "reserved" },
{ 0x04, "IPMI-SMBus" },
{ 0x05, "KCS" },
{ 0x06, "SMIC" },
{ 0x07, "BT-10" },
{ 0x08, "BT-15" },
{ 0x09, "TMode" },
{ 0x1c, "OEM 1" },
{ 0x1d, "OEM 2" },
{ 0x1e, "OEM 3" },
{ 0x1f, "OEM 4" },
{ 0x00, NULL },
};
static const struct valstr ipmi_channel_medium_vals[] = {
{ 0x00, "reserved" },
{ 0x01, "IPMB (I2C)" },
{ 0x02, "ICMB v1.0" },
{ 0x03, "ICMB v0.9" },
{ 0x04, "802.3 LAN" },
{ 0x05, "Serial/Modem" },
{ 0x06, "Other LAN" },
{ 0x07, "PCI SMBus" },
{ 0x08, "SMBus v1.0/v1.1" },
{ 0x09, "SMBus v2.0" },
{ 0x0a, "USB 1.x" },
{ 0x0b, "USB 2.x" },
{ 0x0c, "System Interface" },
{ 0x00, NULL },
};
static struct lan_param *
get_lan_param(struct ipmi_intf * intf, unsigned char chan, int param)
@ -137,12 +85,60 @@ get_lan_param(struct ipmi_intf * intf, unsigned char chan, int param)
return NULL;
p->data = rsp->data + 1;
p->data_len = rsp->data_len-1;
return p;
}
/* wait for Set LAN Parameter command to complete
* this may take a long time...
*/
static int
set_lan_param(struct ipmi_intf * intf, unsigned char chan, int param, unsigned char * data, int len)
set_lan_param_wait(struct ipmi_intf * intf, unsigned char chan, int param, unsigned char * data, int len)
{
struct lan_param * p;
int timeout = 3; /* 3 second timeout */
int retry = 10; /* 10 retries */
if (verbose > 1) {
printf("Waiting for Set LAN Parameter to complete...\n");
printbuf(data, len, "SET DATA");
}
for (;;) {
p = get_lan_param(intf, chan, param);
if (!p) {
sleep(timeout);
if (!retry--)
return -1;
continue;
}
if (verbose > 1)
printbuf(p->data, p->data_len, "READ DATA");
if (p->data_len != len) {
sleep(timeout);
if (!retry--) {
printf("Mismatched data lengths: %d != %d\n",
p->data_len, len);
return -1;
}
continue;
}
if (memcmp(data, p->data, len) != 0) {
sleep(timeout);
if (!retry--) {
printf("LAN Parameter Data does not match! "
"Write may have failed.\n");
return -1;
}
continue;
}
return 0;
}
}
static int
__set_lan_param(struct ipmi_intf * intf, unsigned char chan, int param, unsigned char * data, int len, int wait)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
@ -163,138 +159,86 @@ set_lan_param(struct ipmi_intf * intf, unsigned char chan, int param, unsigned c
req.msg.data_len = len+2;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
if (!rsp) {
printf("Set Lan Parameter failed\n");
return -1;
}
if (rsp->ccode && wait) {
if (verbose)
printf("Warning: Set Lan Parameter failed: %s\n",
val2str(rsp->ccode, completion_code_vals));
if (rsp->ccode == 0xcc) {
/* retry hack for invalid data field ccode */
int timeout = 3; /* 3 second timeout */
int retry = 10; /* 10 retries */
printf("Retrying...\n");
for (;;) {
if (!retry--)
break;
sleep(timeout);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
continue;
return wait ? set_lan_param_wait(intf, chan, param, data, len) : 0;
}
}
else if (rsp->ccode != 0xff) {
/* let 0xff ccode continue */
return -1;
}
}
return 0;
return wait ? set_lan_param_wait(intf, chan, param, data, len) : 0;
}
void
ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel)
static int
ipmi_lanp_lock_state(struct ipmi_intf * intf, unsigned char chan)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[2];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x42;
req.msg.data = &channel;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get Channel Info Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return;
}
if (!verbose)
return;
printf("Channel 0x%x info:\n", rsp->data[0] & 0xf);
printf(" Channel Medium Type : %s\n",
val2str(rsp->data[1] & 0x7f, ipmi_channel_medium_vals));
printf(" Channel Protocol Type : %s\n",
val2str(rsp->data[2] & 0x1f, ipmi_channel_protocol_vals));
printf(" Session Support : ");
switch (rsp->data[3] & 0xc0) {
case 0x00:
printf("session-less\n");
break;
case 0x40:
printf("single-session\n");
break;
case 0x80:
printf("multi-session\n");
break;
case 0xc0:
default:
printf("session-based\n");
break;
}
printf(" Active Session Count : %d\n",
rsp->data[3] & 0x3f);
printf(" Protocol Vendor ID : %d\n",
rsp->data[4] | rsp->data[5] << 8 | rsp->data[6] << 16);
memset(&req, 0, sizeof(req));
rqdata[0] = channel & 0xf;
/* get volatile settings */
rqdata[1] = 0x80; /* 0x80=active */
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x41;
req.msg.data = rqdata;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
return;
}
printf(" Volatile(active) Settings\n");
printf(" Alerting : %sabled\n", (rsp->data[0] & 0x20) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n", (rsp->data[0] & 0x10) ? "dis" : "en");
printf(" User Level Auth : %sabled\n", (rsp->data[0] & 0x08) ? "dis" : "en");
printf(" Access Mode : ");
switch (rsp->data[0] & 0x7) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
/* get non-volatile settings */
rqdata[1] = 0x40; /* 0x40=non-volatile */
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
return;
}
printf(" Non-Volatile Settings\n");
printf(" Alerting : %sabled\n", (rsp->data[0] & 0x20) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n", (rsp->data[0] & 0x10) ? "dis" : "en");
printf(" User Level Auth : %sabled\n", (rsp->data[0] & 0x08) ? "dis" : "en");
printf(" Access Mode : ");
switch (rsp->data[0] & 0x7) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
struct lan_param * p;
p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS);
return p->data[0] & 1;
}
static void
ipmi_lanp_lock(struct ipmi_intf * intf, unsigned char chan)
{
unsigned char val = 1;
int inp, try = 3;
while ((inp = ipmi_lanp_lock_state(intf, chan)) != val) {
if (!try--)
break;
__set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0);
}
}
static void
ipmi_lanp_unlock(struct ipmi_intf * intf, unsigned char chan)
{
unsigned char val;
int rc;
val = 2;
rc = __set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 1, 0);
if (rc < 0) {
if (verbose > 1)
printf("LAN Parameter Commit not supported. Clearing Set In Progress...\n");
val = 0;
__set_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS, &val, 0, 0);
}
}
static int
set_lan_param(struct ipmi_intf * intf, unsigned char chan, int param, unsigned char * data, int len)
{
int rc;
ipmi_lanp_lock(intf, chan);
rc = __set_lan_param(intf, chan, param, data, len, 1);
ipmi_lanp_unlock(intf, chan);
return rc;
}
static void
lan_set_arp_interval(struct ipmi_intf * intf, unsigned char chan, unsigned char * ival)
{
@ -361,6 +305,9 @@ ipmi_lan_print(struct ipmi_intf * intf, unsigned char chan)
{
struct lan_param * p;
p = get_lan_param(intf, chan, IPMI_LANP_SET_IN_PROGRESS);
if (p) printf("%-24s: 0x%02x\n", p->desc, p->data[0]);
p = get_lan_param(intf, chan, IPMI_LANP_AUTH_TYPE);
if (p) printf("%-24s: 0x%02x\n", p->desc, p->data[0]);
@ -485,7 +432,9 @@ ipmi_lan_set_password(struct ipmi_intf * intf,
memset(&data, 0, sizeof(data));
data[0] = userid & 0x3f;/* user ID */
data[1] = 0x02; /* set password */
memcpy(data+2, password, (strlen(password) > 16) ? 16 : strlen(password));
if (password)
memcpy(data+2, password, min(strlen(password), 16));
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
@ -504,11 +453,11 @@ ipmi_lan_set_password(struct ipmi_intf * intf,
/* adjust our session password
* or we will no longer be able to communicate with BMC
*/
lan_session.password = 1;
memset(lan_session.authcode, 0, 16);
memcpy(lan_session.authcode, password, strlen(password));
printf("Password for user %d set to %s\n", userid, lan_session.authcode);
ipmi_intf_session_set_password(intf, password);
if (password)
printf("Password for user %d set to %s\n", userid, password);
else
printf("Password cleared for user %d\n", userid);
}
static int
@ -617,6 +566,34 @@ get_cmdline_ipaddr(char * arg, unsigned char * buf)
return 0;
}
static void ipmi_lan_set_usage(void)
{
printf("\nusage: lan set <channel> <command> [option]\n\n");
printf("LAN set commands:\n");
printf(" ipaddr <x.x.x.x> Set channel IP address\n");
printf(" netmask <x.x.x.x> Set channel IP netmask\n");
printf(" macaddr <x:x:x:x:x:x> Set channel MAC address\n");
printf(" defgw ipaddr <x.x.x.x> Set default gateway IP address\n");
printf(" defgw macaddr <x:x:x:x:x:x> Set default gateway MAC address\n");
printf(" bakgw ipaddr <x.x.x.x> Set backup gateway IP address\n");
printf(" bakgw macaddr <x:x:x:x:x:x> Set backup gateway MAC address\n");
printf(" password <password> Set session password for this channel\n");
printf(" snmp <community string> Set SNMP public community string\n");
printf(" access <on|off> Enable or disable access to this channel\n");
printf(" arp response <on|off> Enable or disable BMC ARP responding\n");
printf(" arp generate <on|off> Enable or disable BMC gratuitous ARP generation\n");
printf(" arp interval <seconds> Set gratuitous ARP generation interval\n");
printf(" auth <level> <type,..> Set channel authentication types\n");
printf(" level = callback, user, operator, admin\n");
printf(" type = none, md2, md5, key\n");
printf(" ipsrc <source> Set IP Address source\n");
printf(" none = unspecified source\n");
printf(" static = address manually configured to be static\n");
printf(" dhcp = address obtained by BMC running DHCP\n");
printf(" bios = address loaded by BIOS or system software\n");
printf("\n");
}
static void
ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
{
@ -624,26 +601,26 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
unsigned char chan;
memset(&data, 0, sizeof(data));
if (argc < 2 || !strncmp(argv[0], "help", 4)) {
printf("usage: lan set <channel> <command>\n");
printf("LAN set commands: ipaddr, netmask, macaddr, defgw, bakgw, password, auth, ipsrc, access, user, arp\n");
if (argc < 1) {
ipmi_lan_set_usage();
return;
}
chan = (unsigned char)strtol(argv[0], NULL, 0);
if (chan != 0x6 && chan != 0x7) {
printf("valid LAN channels are 6 and 7\n");
if (argc < 2 || chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX ||
!strncmp(argv[0], "help", 4) ||
!strncmp(argv[1], "help", 4)) {
ipmi_lan_set_usage();
return;
}
/* set user access */
if (!strncmp(argv[1], "user", 4)) {
ipmi_set_user_access(intf, chan, 1);
return;
}
/* set channel access mode */
if (!strncmp(argv[1], "access", 6)) {
else if (!strncmp(argv[1], "access", 6)) {
if (argc < 3 || !strncmp(argv[2], "help", 4)) {
printf("lan set access <on|off>\n");
}
@ -656,11 +633,9 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
else {
printf("lan set access <on|off>\n");
}
return;
}
/* set ARP control */
if (!strncmp(argv[1], "arp", 3)) {
else if (!strncmp(argv[1], "arp", 3)) {
if (argc < 3 || !strncmp(argv[2], "help", 4)) {
printf("lan set <channel> arp respond <on|off>\n");
printf("lan set <channel> arp generate <on|off>\n");
@ -695,11 +670,9 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
printf("lan set <channel> arp generate <on|off>\n");
printf("lan set <channel> arp interval <seconds>\n");
}
return;
}
/* set authentication types */
if (!strncmp(argv[1], "auth", 4)) {
else if (!strncmp(argv[1], "auth", 4)) {
if (argc < 3 || !strncmp(argv[2], "help", 4)) {
printf("lan set <channel> auth <level> <type,type,...>\n");
printf(" level = callback, user, operator, admin\n");
@ -708,7 +681,6 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
return;
}
ipmi_lan_set_auth(intf, chan, argv[2], argv[3]);
return;
}
/* ip address source */
else if (!strncmp(argv[1], "ipsrc", 5)) {
@ -737,6 +709,17 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
else if (!strncmp(argv[1], "password", 8)) {
ipmi_lan_set_password(intf, 1, argv[2]);
}
/* snmp community string */
else if (!strncmp(argv[1], "snmp", 4)) {
if (argc < 3 || !strncmp(argv[2], "help", 4)) {
printf("lan set <channel> snmp <community string>\n");
return;
}
memcpy(data, argv[2], min(strlen(argv[2]), 18));
printf("Setting LAN %s to %s\n",
ipmi_lan_params[IPMI_LANP_SNMP_STRING].desc, data);
set_lan_param(intf, chan, IPMI_LANP_SNMP_STRING, data, 18);
}
/* ip address */
else if (!strncmp(argv[1], "ipaddr", 6) &&
!get_cmdline_ipaddr(argv[2], data)) {
@ -744,9 +727,6 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
ipmi_lan_params[IPMI_LANP_IP_ADDR].desc,
data[0], data[1], data[2], data[3]);
set_lan_param(intf, chan, IPMI_LANP_IP_ADDR, data, 4);
/* also set ip address source to "static" */
data[0] = 0x1;
set_lan_param(intf, chan, IPMI_LANP_IP_ADDR_SRC, data, 1);
}
/* network mask */
else if (!strncmp(argv[1], "netmask", 7) &&
@ -809,14 +789,22 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv)
int
ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv)
{
if (!argc || !strncmp(argv[0], "help", 4))
if (!argc || !strncmp(argv[0], "help", 4)) {
printf("LAN Commands: print, set\n");
else if (!strncmp(argv[0], "printconf", 9) ||
!strncmp(argv[0], "print", 5)) {
return 0;
}
/* all the lan parameters commands need admin level */
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
if (!strncmp(argv[0], "printconf", 9) || !strncmp(argv[0], "print", 5)) {
unsigned char chan = 7;
if (argc > 1)
chan = (unsigned char)strtol(argv[1], NULL, 0);
ipmi_lan_print(intf, chan);
if (chan < 1 || chan > IPMI_CHANNEL_NUMBER_MAX)
printf("usage: lan print <channel>\n");
else
ipmi_lan_print(intf, chan);
}
else if (!strncmp(argv[0], "set", 3))
ipmi_lan_set(intf, argc-1, &(argv[1]));

105
ipmitool/lib/ipmi_raw.c Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_raw.h>
int ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char netfn, cmd;
int i;
unsigned char data[32];
if (argc < 2 || !strncmp(argv[0], "help", 4)) {
printf("RAW Commands: raw <netfn> <cmd> [data]\n");
return -1;
}
netfn = (unsigned char)strtol(argv[0], NULL, 0);
cmd = (unsigned char)strtol(argv[1], NULL, 0);
memset(data, 0, sizeof(data));
memset(&req, 0, sizeof(req));
req.msg.netfn = netfn;
req.msg.cmd = cmd;
req.msg.data = data;
for (i=2; i<argc; i++) {
unsigned char val = (unsigned char)strtol(argv[i], NULL, 0);
req.msg.data[i-2] = val;
req.msg.data_len++;
}
if (verbose && req.msg.data_len) {
for (i=0; i<req.msg.data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", req.msg.data[i]);
}
printf("\n");
}
if (verbose)
printf("RAW REQ (netfn=0x%x cmd=0x%x data_len=%d)\n",
req.msg.netfn, req.msg.cmd, req.msg.data_len);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x sending RAW command\n",
rsp ? rsp->ccode : 0);
return -1;
}
if (verbose)
printf("RAW RSP (%d bytes)\n", rsp->data_len);
for (i=0; i<rsp->data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", rsp->data[i]);
}
printf("\n");
return 0;
}

View File

@ -37,16 +37,27 @@
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_entity.h>
#include <ipmitool/ipmi_constants.h>
#if HAVE_CONFIG_H
# include <config.h>
#endif
extern int verbose;
static int sdr_max_read_len = GET_SDR_ENTIRE_RECORD;
static struct sdr_record_list * sdr_list_head = NULL;
static struct ipmi_sdr_iterator * sdr_list_itr = NULL;
/* convert unsigned value to 2's complement signed */
int utos(unsigned val, unsigned bits)
@ -84,6 +95,29 @@ sdr_convert_sensor_reading(struct sdr_record_full_sensor * sensor, unsigned char
}
}
unsigned char
sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor * sensor, float val)
{
int m, b, k1, k2;
double result;
m = __TO_M(sensor->mtol);
b = __TO_B(sensor->bacc);
k1 = __TO_B_EXP(sensor->bacc);
k2 = __TO_R_EXP(sensor->bacc);
if (sensor->unit.analog > 2) /* This isn't an analog sensor. */
return 0;
if (m == 0) /* don't divide by zero */
return 0;
result = ((val / pow(10, k2)) - (b * pow(10, k1))) / m;
if ((result -(int)result) >= .5)
return (unsigned char)ceil(result);
else
return (unsigned char)result;
}
#define READING_UNAVAILABLE 0x20
#define SCANNING_DISABLED 0x80
@ -109,7 +143,7 @@ ipmi_sdr_get_sensor_reading(struct ipmi_intf * intf, unsigned char sensor)
return rsp;
}
static const char *
const char *
ipmi_sdr_get_sensor_type_desc(const unsigned char type)
{
if (type <= SENSOR_TYPE_MAX)
@ -161,7 +195,7 @@ ipmi_sdr_get_header(struct ipmi_intf * intf, unsigned short reserve_id, unsigned
req.msg.data_len = sizeof(sdr_rq);
rsp = intf->sendrecv(intf, &req);
if (!rsp || !rsp->data_len) {
if (!rsp || !rsp->data_len || rsp->ccode) {
printf("Error getting SDR record id 0x%04x\n", record_id);
return NULL;
}
@ -191,7 +225,7 @@ ipmi_sdr_get_next_header(struct ipmi_intf * intf, struct ipmi_sdr_iterator * itr
{
struct sdr_get_rs *header;
if (itr->next > itr->total)
if (itr->next == 0xffff)
return NULL;
if (!(header = ipmi_sdr_get_header(intf, itr->reservation, itr->next)))
@ -211,9 +245,8 @@ static inline int get_offset(unsigned char x)
return 0;
}
static void
ipmi_sdr_print_sensor_full(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
void ipmi_sdr_print_sensor_full(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
{
char sval[16], unitstr[16], desc[17];
int i=0, validread=1, do_unit=1;
@ -293,14 +326,13 @@ ipmi_sdr_print_sensor_full(struct ipmi_intf * intf,
*/
printf("%s,", sensor->id_code ? desc : NULL);
if (validread)
if (validread) {
printf("%.*f,", (val==(int)val) ? 0 : 3, val);
else
printf(",");
printf("%s,%s", do_unit ? unitstr : "",
ipmi_sdr_get_status(rsp->data[2]));
} else
printf(",,%s", ipmi_sdr_get_status(rsp->data[2]));
printf("%s,%s",
do_unit ? unitstr : "",
ipmi_sdr_get_status(rsp->data[2]));
if (verbose)
{
@ -450,28 +482,28 @@ ipmi_sdr_print_sensor_full(struct ipmi_intf * intf,
else
printf("Lower non-critical : Unspecified\n");
min_reading = sdr_convert_sensor_reading(sensor, sensor->sensor_min);
min_reading = (unsigned char)sdr_convert_sensor_reading(sensor, sensor->sensor_min);
if ((sensor->unit.analog == 0 && sensor->sensor_min == 0x00) ||
(sensor->unit.analog == 1 && sensor->sensor_min == 0xff) ||
(sensor->unit.analog == 2 && sensor->sensor_min == 0x80))
printf("Minimum sensor range : Unspecified\n");
else
printf("Minimum sensor range : %.3f\n", min_reading);
printf("Minimum sensor range : %.3f\n", (float)min_reading);
max_reading = sdr_convert_sensor_reading(sensor, sensor->sensor_max);
max_reading = (unsigned char)sdr_convert_sensor_reading(sensor, sensor->sensor_max);
if ((sensor->unit.analog == 0 && sensor->sensor_max == 0xff) ||
(sensor->unit.analog == 1 && sensor->sensor_max == 0x00) ||
(sensor->unit.analog == 2 && sensor->sensor_max == 0x7f))
printf("Maximum sensor range : Unspecified\n");
else
printf("Maximum sensor range : %.3f\n", max_reading);
printf("Maximum sensor range : %.3f\n", (float)max_reading);
} else { /* discrete */
printf("Sensor Type (Discete) : %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.type));
printf("Sensor Reading : ");
if (validread)
printf("%xh\n", val);
printf("%xh\n", (unsigned int)val);
else
printf("not present\n");
@ -483,9 +515,8 @@ ipmi_sdr_print_sensor_full(struct ipmi_intf * intf,
}
}
static void
ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf,
struct sdr_record_compact_sensor * sensor)
void ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf,
struct sdr_record_compact_sensor * sensor)
{
struct ipmi_rs * rsp;
char desc[17];
@ -511,8 +542,16 @@ ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf,
return;
}
if (!rsp->ccode && (!(rsp->data[1] & 0x80)))
if (rsp->ccode) {
if (verbose > 1)
printf("Invalid ccode: %x\n", rsp->ccode);
return;
}
if (!(rsp->data[1] & 0x80)) {
if (verbose > 1)
printf("Sensor %x scanning disabled\n", sensor->keys.sensor_num);
return; /* sensor scanning disabled */
}
if (verbose) {
printf("Sensor ID : %s (0x%x)\n",
@ -549,7 +588,7 @@ ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf,
char temp[18];
if ((rsp->ccode == 0xcd) || (rsp->data[1] & READING_UNAVAILABLE)) {
state = "Not Readable ";
state = csv_output ? "Not Readable" : "Not Readable ";
} else {
switch (sensor->sensor.type) {
case 0x07: /* processor */
@ -603,9 +642,8 @@ ipmi_sdr_print_sensor_compact(struct ipmi_intf * intf,
}
}
static void
ipmi_sdr_print_sensor_eventonly(struct ipmi_intf * intf,
struct sdr_record_eventonly_sensor * sensor)
void ipmi_sdr_print_sensor_eventonly(struct ipmi_intf * intf,
struct sdr_record_eventonly_sensor * sensor)
{
char desc[17];
@ -633,15 +671,14 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf * intf,
else {
char * state = "Event-Only ";
if (csv_output)
printf("%s,%s,ns", sensor->id_code ? desc : NULL, state);
printf("%s,Event-Only,ns\n", sensor->id_code ? desc : NULL);
else
printf("%-16s | %-17s | ns\n", sensor->id_code ? desc : NULL, state);
}
}
static void
ipmi_sdr_print_mc_locator(struct ipmi_intf * intf,
struct sdr_record_mc_locator * mc)
void ipmi_sdr_print_mc_locator(struct ipmi_intf * intf,
struct sdr_record_mc_locator * mc)
{
char desc[17];
@ -714,9 +751,8 @@ ipmi_sdr_print_mc_locator(struct ipmi_intf * intf,
printf("\n");
}
static void
ipmi_sdr_print_fru_locator(struct ipmi_intf * intf,
struct sdr_record_fru_locator * fru)
void ipmi_sdr_print_fru_locator(struct ipmi_intf * intf,
struct sdr_record_fru_locator * fru)
{
char desc[17];
@ -760,8 +796,76 @@ ipmi_sdr_print_fru_locator(struct ipmi_intf * intf,
printf("\n");
}
void
ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type)
static
void ipmi_sdr_print_oem(struct ipmi_intf * intf, unsigned char * data, int len)
{
if (verbose > 2)
printbuf(data, len, "OEM Record");
/* intel manufacturer id */
if (data[0] == 0x57 && data[1] == 0x01 && data[2] == 0x00) {
switch (data[3]) { /* record sub-type */
case 0x02: /* Power Unit Map */
if (verbose) {
printf("Sensor ID : Power Unit Redundancy (0x%x)\n",
data[4]);
printf("Sensor Type : Intel OEM - Power Unit Map\n");
printf("Redundant Supplies : %d", data[6]);
if (data[5])
printf(" (flags %xh)", data[5]);
printf("\n");
}
switch (len) {
case 7: /* SR1300, non-redundant */
if (verbose)
printf("Power Redundancy : No\n");
else if (csv_output)
printf("Power Redundancy,Not Available,nr\n");
else
printf("Power Redundancy | Not Available | nr\n");
break;
case 8: /* SR2300, redundant, PS1 & PS2 present */
if (verbose) {
printf("Power Redundancy : No\n");
printf("Power Supply 2 Sensor : %x\n", data[8]);
} else if (csv_output) {
printf("Power Redundancy,PS@%02xh,nr\n", data[8]);
} else {
printf("Power Redundancy | PS@%02xh | nr\n",
data[8]);
}
case 9: /* SR2300, non-redundant, PSx present */
if (verbose) {
printf("Power Redundancy : Yes\n");
printf("Power Supply Sensor : %x\n", data[7]);
printf("Power Supply Sensor : %x\n", data[8]);
} else if (csv_output) {
printf("Power Redundancy,PS@%02xh + PS@%02xh,ok\n",
data[7], data[8]);
} else {
printf("Power Redundancy | PS@%02xh + PS@%02xh | ok\n",
data[7], data[8]);
}
break;
}
if (verbose)
printf("\n");
break;
case 0x03: /* Fan Speed Control */
break;
case 0x06: /* System Information */
break;
case 0x07: /* Ambient Temperature Fan Speed Control */
break;
default:
if (verbose > 1)
printf("Unknown Intel OEM SDR Record type %02x\n", data[3]);
}
}
}
void ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type)
{
struct sdr_get_rs * header;
struct ipmi_sdr_iterator * itr;
@ -775,7 +879,7 @@ ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type)
return;
}
while (header = ipmi_sdr_get_next_header(intf, itr)) {
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
unsigned char * rec;
if (type != header->type && type != 0xff)
@ -817,6 +921,7 @@ ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type)
case SDR_RECORD_TYPE_BMC_MSG_CHANNEL_INFO:
break;
case SDR_RECORD_TYPE_OEM:
ipmi_sdr_print_oem(intf, rec, header->length);
break;
}
free(rec);
@ -825,6 +930,29 @@ ipmi_sdr_print_sdr(struct ipmi_intf * intf, unsigned char type)
ipmi_sdr_end(intf, itr);
}
int
ipmi_sdr_get_reservation (struct ipmi_intf * intf, unsigned short *reserve_id)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
/* obtain reservation ID */
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_SDR_RESERVE_REPO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || !rsp->data_len || rsp->ccode)
return 0;
*reserve_id = ((struct sdr_reserve_repo_rs *) &(rsp->data))->reserve_id;
if (verbose > 1)
printf("SDR reserveration ID %04x\n", *reserve_id);
return 1;
}
struct ipmi_sdr_iterator *
ipmi_sdr_start(struct ipmi_intf * intf)
{
@ -832,8 +960,6 @@ ipmi_sdr_start(struct ipmi_intf * intf)
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct sdr_repo_info_rs sdr_info;
struct sdr_reserve_repo_rs sdr_reserve;
struct sdr_get_rs * header;
if (!(itr = malloc (sizeof (struct ipmi_sdr_iterator))))
return NULL;
@ -844,7 +970,7 @@ ipmi_sdr_start(struct ipmi_intf * intf)
req.msg.cmd = GET_SDR_REPO_INFO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || !rsp->data_len)
if (!rsp || !rsp->data_len || rsp->ccode)
{
free (itr);
return NULL;
@ -852,7 +978,7 @@ ipmi_sdr_start(struct ipmi_intf * intf)
memcpy(&sdr_info, rsp->data, sizeof(sdr_info));
/* byte 1 is SDR version, should be 51h */
if (sdr_info.version != 0x51) {
if ((sdr_info.version != 0x51) && (sdr_info.version != 0x01)) {
printf("SDR repository version mismatch!\n");
free (itr);
return NULL;
@ -863,20 +989,11 @@ ipmi_sdr_start(struct ipmi_intf * intf)
printf("SDR records: %d\n", sdr_info.count);
}
/* obtain reservation ID */
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_SDR_RESERVE_REPO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || !rsp->data_len)
if (!ipmi_sdr_get_reservation (intf, &(itr->reservation)))
{
free (itr);
return NULL;
}
memcpy(&sdr_reserve, rsp->data, sizeof(sdr_reserve));
itr->reservation = sdr_reserve.reserve_id;
if (verbose > 1)
printf("SDR reserveration ID %04x\n", sdr_reserve.reserve_id);
itr->next = 0;
@ -891,10 +1008,11 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header,
struct ipmi_rs * rsp;
struct sdr_get_rq sdr_rq;
unsigned char * data;
int i, len = header->length;
int i = 0, len = header->length;
if (!(data = malloc(len+1)))
return NULL;
memset(data, 0, len+1);
memset(&sdr_rq, 0, sizeof(sdr_rq));
@ -908,19 +1026,51 @@ ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header,
req.msg.data = (unsigned char *)&sdr_rq;
req.msg.data_len = sizeof(sdr_rq);
/* read SDR record with partial (30 byte) reads
* because a full read (0xff) exceeds the maximum
/* read SDR record with partial reads
* because a full read usually exceeds the maximum
* transport buffer size. (completion code 0xca)
*/
for (i=0; i<len; i+=GET_SDR_MAX_LEN) {
sdr_rq.length = (len-i < GET_SDR_MAX_LEN) ? len-i : GET_SDR_MAX_LEN;
while (i < len) {
sdr_rq.length = (len-i < sdr_max_read_len) ? len-i : sdr_max_read_len;
sdr_rq.offset = i+5; /* 5 header bytes */
if (verbose > 1)
printf("getting %d bytes from SDR at offset %d\n",
sdr_rq.length, sdr_rq.offset);
rsp = intf->sendrecv(intf, &req);
if (rsp && rsp->data)
memcpy(data+i, rsp->data+2, sdr_rq.length);
if (!rsp) {
free (data);
return NULL;
}
switch (rsp->ccode) {
case 0xca:
/* read too many bytes at once */
sdr_max_read_len = (sdr_max_read_len >> 1) - 1;
continue;
case 0xc5:
/* lost reservation */
if (verbose > 1)
printf("SDR reserveration canceled. "
"Sleeping a bit and retrying...\n");
sleep (rand () & 3);
if (!ipmi_sdr_get_reservation (intf, &(itr->reservation))) {
free (data);
return NULL;
}
sdr_rq.reserve_id = itr->reservation;
continue;
}
if (!rsp->data_len || rsp->ccode) {
free(data);
return NULL;
}
memcpy(data+i, rsp->data+2, sdr_rq.length);
i += sdr_max_read_len;
}
return data;
@ -932,18 +1082,381 @@ ipmi_sdr_end(struct ipmi_intf * intf, struct ipmi_sdr_iterator * itr)
free (itr);
}
struct sdr_record_list *
ipmi_sdr_find_sdr_byid(struct ipmi_intf * intf, char * id)
{
struct sdr_get_rs * header;
static struct sdr_record_list * sdr_list_tail;
static struct sdr_record_list * e;
int found = 0;
if (!sdr_list_itr) {
sdr_list_itr = ipmi_sdr_start(intf);
if (!sdr_list_itr) {
printf("Unable to open SDR for reading\n");
return NULL;
}
}
/* check what we've already read */
e = sdr_list_head;
while (e) {
switch (e->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
if (!strncmp(e->record.full->id_string, id,
e->record.full->id_code & 0x1f))
return e;
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
if (!strncmp(e->record.compact->id_string, id,
e->record.compact->id_code & 0x1f))
return e;
break;
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
if (!strncmp(e->record.eventonly->id_string, id,
e->record.eventonly->id_code & 0x1f))
return e;
break;
case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
if (!strncmp(e->record.fruloc->id_string, id,
e->record.fruloc->id_code & 0x1f))
return e;
break;
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
if (!strncmp(e->record.mcloc->id_string, id,
e->record.mcloc->id_code & 0x1f))
return e;
break;
}
e = e->next;
}
/* now keep looking */
while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) {
unsigned char * rec;
struct sdr_record_list * sdrr;
sdrr = malloc(sizeof(struct sdr_record_list));
memset(sdrr, 0, sizeof(struct sdr_record_list));
sdrr->id = header->id;
sdrr->type = header->type;
rec = ipmi_sdr_get_record(intf, header, sdr_list_itr);
if (!rec)
continue;
switch (header->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
sdrr->record.full = (struct sdr_record_full_sensor *)rec;
if (!strncmp(sdrr->record.full->id_string, id,
sdrr->record.full->id_code & 0x1f))
found = 1;
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
sdrr->record.compact = (struct sdr_record_compact_sensor *)rec;
if (!strncmp(sdrr->record.compact->id_string, id,
sdrr->record.compact->id_code & 0x1f))
found = 1;
break;
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
sdrr->record.eventonly = (struct sdr_record_eventonly_sensor *)rec;
if (!strncmp(sdrr->record.eventonly->id_string, id,
sdrr->record.eventonly->id_code & 0x1f))
found = 1;
break;
case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
sdrr->record.fruloc = (struct sdr_record_fru_locator *)rec;
if (!strncmp(sdrr->record.fruloc->id_string, id,
sdrr->record.fruloc->id_code & 0x1f))
found = 1;
break;
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
sdrr->record.mcloc = (struct sdr_record_mc_locator *)rec;
if (!strncmp(sdrr->record.mcloc->id_string, id,
sdrr->record.mcloc->id_code & 0x1f))
found = 1;
break;
default:
free(rec);
continue;
}
if (!sdr_list_head)
sdr_list_head = sdrr;
else
sdr_list_tail->next = sdrr;
sdr_list_tail = sdrr;
if (found)
return sdrr;
}
return NULL;
}
void ipmi_sdr_list_empty(struct ipmi_intf * intf)
{
struct sdr_record_list *list, *next;
ipmi_sdr_end(intf, sdr_list_itr);
list = sdr_list_head;
while (list) {
switch (list->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
if (list->record.full)
free(list->record.full);
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
if (list->record.compact)
free(list->record.compact);
break;
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
if (list->record.eventonly)
free(list->record.eventonly);
break;
case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
if (list->record.fruloc)
free(list->record.fruloc);
break;
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
if (list->record.mcloc)
free(list->record.mcloc);
break;
}
next = list->next;
free(list);
list = next;
}
}
/*
* ipmi_sdr_get_info
*
* Execute the GET SDR REPOSITORY INFO command, and populate the sdr_info
* structure.
* See section 33.9 of the IPMI v2 specification for details
*
* returns 0 on success
* -1 on transport error
* > 0 for other errors
*/
int
ipmi_sdr_get_info(struct ipmi_intf * intf,
struct get_sdr_repository_info_rsp * sdr_repository_info)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE; // 0x0A
req.msg.cmd = IPMI_GET_SDR_REPOSITORY_INFO; // 0x20
req.msg.data = 0;
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
printf("Error:%x Get SDR Repository Info Command\n",
rsp ? rsp->ccode : 0);
return (rsp? rsp->ccode : -1);
}
memcpy(sdr_repository_info,
rsp->data,
min(sizeof(struct get_sdr_repository_info_rsp),rsp->data_len));
return 0;
}
static char *
ipmi_sdr_timestamp(uint32_t stamp)
{
static char tbuf[40];
time_t s = (time_t)stamp;
memset(tbuf, 0, 40);
if (stamp)
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s));
return tbuf;
}
/*
* ipmi_sdr_print_info
*
* Display the return data of the GET SDR REPOSITORY INFO command
* See section 33.9 of the IPMI v2 specification for details
*
* returns 0 on success
* -1 on error
*/
int
ipmi_sdr_print_info(struct ipmi_intf * intf)
{
uint32_t timestamp;
uint16_t free_space;
struct get_sdr_repository_info_rsp sdr_repository_info;
if (ipmi_sdr_get_info(intf, &sdr_repository_info) != 0)
return -1;
printf("SDR Version : 0x%x\n",
sdr_repository_info.sdr_version);
printf("Record Count : %d\n",
(sdr_repository_info.record_count_msb << 8) |
sdr_repository_info.record_count_lsb);
free_space =
(sdr_repository_info.free_space[0] << 8) |
sdr_repository_info.free_space[1];
printf("Free Space : ");
switch (free_space)
{
case 0x0000:
printf("none (full)\n");
break;
case 0xFFFF:
printf("unspecified\n");
break;
case 0xFFFE:
printf("> 64Kb - 2 bytes\n");
break;
default:
printf("%d bytes\n", free_space);
break;
}
timestamp =
(sdr_repository_info.most_recent_addition_timestamp[3] << 24) |
(sdr_repository_info.most_recent_addition_timestamp[2] << 16) |
(sdr_repository_info.most_recent_addition_timestamp[1] << 8) |
sdr_repository_info.most_recent_addition_timestamp[0];
printf("Most recent Addition : %s\n",
ipmi_sdr_timestamp(timestamp));
timestamp =
(sdr_repository_info.most_recent_erase_timestamp[3] << 24) |
(sdr_repository_info.most_recent_erase_timestamp[2] << 16) |
(sdr_repository_info.most_recent_erase_timestamp[1] << 8) |
sdr_repository_info.most_recent_erase_timestamp[0];
printf("Most recent Erase : %s\n", ipmi_sdr_timestamp(timestamp));
printf("SDR overflow : %s\n",
(sdr_repository_info.overflow_flag? "yes": "no"));
printf("SDR Repository Update Support : ");
switch (sdr_repository_info.modal_update_support)
{
case 0:
printf("unspecified\n");
break;
case 1:
printf("non-modal\n");
break;
case 2:
printf("modal\n");
break;
case 3:
printf("modal and non-modal\n");
break;
default:
printf("error in response\n");
break;
}
printf("Delete SDR supported : %s\n",
sdr_repository_info.delete_sdr_supported? "yes" : "no");
printf("Partial Add SDR supported : %s\n",
sdr_repository_info.partial_add_sdr_supported? "yes" : "no");
printf("Reserve SDR repository supported : %s\n",
sdr_repository_info.reserve_sdr_repository_supported? "yes" : "no");
printf("SDR Repository Alloc info supported : %s\n",
sdr_repository_info.delete_sdr_supported? "yes" : "no");
return 0;
}
static int ipmi_sdr_dump_bin(struct ipmi_intf * intf, const char * ofile)
{
struct sdr_get_rs * header;
struct ipmi_sdr_iterator * itr;
FILE * fp;
fp = ipmi_open_file_write(ofile);
if (!fp) {
return -1;
}
/* open connection to SDR */
itr = ipmi_sdr_start(intf);
if (!itr) {
printf("Unable to open SDR for reading\n");
fclose(fp);
return -1;
}
printf("Dumping Sensor Data Repository to '%s'\n", ofile);
/* go through sdr records */
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
int r;
unsigned char h[5];
unsigned char * rec;
if (verbose)
printf("Record ID %04x (%d bytes)\n", header->id, header->length);
rec = ipmi_sdr_get_record(intf, header, itr);
if (!rec) continue;
/* build and write sdr header */
h[0] = header->id & 0xff;
h[1] = (header->id >> 8) & 0xff;
h[2] = header->version;
h[3] = header->type;
h[4] = header->length;
r = fwrite(h, 1, 5, fp);
if (r != 5) {
printf("Error writing header to output file %s\n", ofile);
break;
}
/* write sdr entry */
r = fwrite(rec, 1, header->length, fp);
if (r != header->length) {
printf("Error writing %d record bytes to output file %s\n",
header->length, ofile);
break;
}
}
fclose(fp);
return 0;
}
int ipmi_sdr_main(struct ipmi_intf * intf, int argc, char ** argv)
{
srand (time (NULL));
if (!argc)
ipmi_sdr_print_sdr(intf, 0xff);
else if (!strncmp(argv[0], "help", 4)) {
printf("SDR Commands: list [all|full|compact|event|mcloc|fru]\n");
printf(" all All SDR Records\n");
printf(" full Full Sensor Record\n");
printf(" compact Compact Sensor Record\n");
printf(" event Event-Only Sensor Record\n");
printf(" mcloc Management Controller Locator Record\n");
printf(" fru FRU Locator Record\n");
printf(" all All SDR Records\n");
printf(" full Full Sensor Record\n");
printf(" compact Compact Sensor Record\n");
printf(" event Event-Only Sensor Record\n");
printf(" mcloc Management Controller Locator Record\n");
printf(" fru FRU Locator Record\n");
printf(" info\n");
}
else if (!strncmp(argv[0], "list", 4)) {
if (argc > 1) {
@ -965,7 +1478,16 @@ int ipmi_sdr_main(struct ipmi_intf * intf, int argc, char ** argv)
ipmi_sdr_print_sdr(intf, 0xff);
}
}
else
else if (!strncmp(argv[0], "info", 4)) {
ipmi_sdr_print_info(intf);
}
else if (!strncmp(argv[0], "dump", 4)) {
if (argc < 2)
printf("usage: sdr dump <filename>\n");
else
ipmi_sdr_dump_bin(intf, argv[1]);
} else {
printf("Invalid SDR command: %s\n", argv[0]);
}
return 0;
}

View File

@ -36,9 +36,12 @@
#include <string.h>
#include <math.h>
#define __USE_XOPEN /* glibc2 needs this for strptime */
#include <time.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sel.h>
extern int verbose;
@ -48,22 +51,6 @@ static const struct valstr event_dir_vals[] = {
{ 1, "Deassertion Event" },
};
static int
ipmi_get_event_class(unsigned char code)
{
if (code == 0)
return -1;
if (code == 1)
return IPMI_EVENT_CLASS_THRESHOLD;
if (code >= 0x02 && code <= 0x0b)
return IPMI_EVENT_CLASS_DISCRETE;
if (code == 0x6f)
return IPMI_EVENT_CLASS_DISCRETE;
if (code >= 0x70 && code <= 0x7f)
return IPMI_EVENT_CLASS_OEM;
return -1;
}
static const char *
ipmi_get_event_type(unsigned char code)
{
@ -80,7 +67,35 @@ ipmi_get_event_type(unsigned char code)
return "Reserved";
}
static void
static char *
ipmi_sel_timestamp(uint32_t stamp)
{
static unsigned char tbuf[40];
time_t s = (time_t)stamp;
memset(tbuf, 0, 40);
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s));
return tbuf;
}
static char *
ipmi_sel_timestamp_date(uint32_t stamp)
{
static unsigned char tbuf[11];
time_t s = (time_t)stamp;
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y", localtime(&s));
return tbuf;
}
static char *
ipmi_sel_timestamp_time(uint32_t stamp)
{
static unsigned char tbuf[9];
time_t s = (time_t)stamp;
strftime(tbuf, sizeof(tbuf), "%H:%M:%S", localtime(&s));
return tbuf;
}
void
ipmi_get_event_desc(struct sel_event_record * rec, char ** desc)
{
unsigned char code, offset;
@ -88,6 +103,7 @@ ipmi_get_event_desc(struct sel_event_record * rec, char ** desc)
if (desc == NULL)
return;
*desc = NULL;
if (rec->event_type == 0x6f) {
evt = sensor_specific_types;
@ -113,7 +129,7 @@ ipmi_get_event_desc(struct sel_event_record * rec, char ** desc)
}
}
static const char *
const char *
ipmi_sel_get_sensor_type(unsigned char code)
{
struct ipmi_event_sensor_types *st = sensor_specific_types;
@ -122,7 +138,7 @@ ipmi_sel_get_sensor_type(unsigned char code)
return st->type;
st++;
}
return NULL;
return "Unknown";
}
static void
@ -130,13 +146,17 @@ ipmi_sel_get_info(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned short e, f;
int pctfull = 0;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return;
if (rsp->ccode) {
printf("Error%x in Get SEL Info command\n",
rsp ? rsp->ccode : 0);
return;
@ -145,25 +165,33 @@ ipmi_sel_get_info(struct ipmi_intf * intf)
printbuf(rsp->data, rsp->data_len, "sel_info");
printf("SEL Information\n");
printf(" Version : %x%x\n",
printf("Version : %x%x\n",
(rsp->data[0] & 0xf0) >> 4, rsp->data[0] & 0xf);
printf(" Entries : %d\n",
buf2short(rsp->data + 1));
printf(" Free Space : %d\n",
buf2short(rsp->data + 3));
printf(" Last Add Time : %08lx\n",
buf2long(rsp->data + 5));
printf(" Last Del Time : %08lx\n",
buf2long(rsp->data + 9));
printf(" Overflow : %s\n",
e = buf2short(rsp->data + 1);
f = buf2short(rsp->data + 3);
printf("Entries : %d\n", e);
printf("Free Space : %d\n", f);
if (e) {
e *= 16;
f += e;
pctfull = (int)(100 * ( (double)e / (double)f ));
}
printf("Percent Used : %d%%\n", pctfull);
printf("Last Add Time : %s\n",
ipmi_sel_timestamp(buf2long(rsp->data + 5)));
printf("Last Del Time : %s\n",
ipmi_sel_timestamp(buf2long(rsp->data + 9)));
printf("Overflow : %s\n",
rsp->data[13] & 0x80 ? "true" : "false");
printf(" Delete cmd : %ssupported\n",
printf("Delete cmd : %ssupported\n",
rsp->data[13] & 0x8 ? "" : "un");
printf(" Parial add cmd : %ssupported\n",
printf("Parial add cmd : %ssupported\n",
rsp->data[13] & 0x4 ? "" : "un");
printf(" Reserve cmd : %ssupported\n",
printf("Reserve cmd : %ssupported\n",
rsp->data[13] & 0x2 ? "" : "un");
printf(" Get Alloc Info : %ssupported\n",
printf("Get Alloc Info : %ssupported\n",
rsp->data[13] & 0x1 ? "" : "un");
if (rsp->data[13] & 0x1) {
@ -173,17 +201,19 @@ ipmi_sel_get_info(struct ipmi_intf * intf)
req.msg.cmd = IPMI_CMD_GET_SEL_ALLOC_INFO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return;
if (rsp->ccode) {
printf("error%d in Get SEL Allocation Info command\n",
rsp ? rsp->ccode : 0);
return;
}
printf(" # of Alloc Units : %d\n", buf2short(rsp->data));
printf(" Alloc Unit Size : %d\n", buf2short(rsp->data + 2));
printf(" # Free Units : %d\n", buf2short(rsp->data + 4));
printf(" Largest Free Blk : %d\n", buf2short(rsp->data + 6));
printf(" Max Record Size : %d\n", rsp->data[7]);
printf("# of Alloc Units : %d\n", buf2short(rsp->data));
printf("Alloc Unit Size : %d\n", buf2short(rsp->data + 2));
printf("# Free Units : %d\n", buf2short(rsp->data + 4));
printf("Largest Free Blk : %d\n", buf2short(rsp->data + 6));
printf("Max Record Size : %d\n", rsp->data[7]);
}
}
@ -193,7 +223,6 @@ ipmi_sel_get_std_entry(struct ipmi_intf * intf, unsigned short id, struct sel_ev
struct ipmi_rq req;
struct ipmi_rs * rsp;
unsigned char msg_data[6];
unsigned char type;
memset(msg_data, 0, 6);
msg_data[0] = 0x00; /* no reserve id, not partial get */
@ -210,7 +239,9 @@ ipmi_sel_get_std_entry(struct ipmi_intf * intf, unsigned short id, struct sel_ev
req.msg.data_len = 6;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return 0;
if (rsp->ccode) {
printf("Error %x in Get SEL Entry %x Command\n",
rsp ? rsp->ccode : 0, id);
return 0;
@ -220,8 +251,9 @@ ipmi_sel_get_std_entry(struct ipmi_intf * intf, unsigned short id, struct sel_ev
if (rsp->data[4] >= 0xc0) {
printf("Not a standard SEL Entry!\n");
return 0;
if (verbose)
printf("Entry %04xh not a standard SEL entry!\n", id);
return (rsp->data[1] << 8) | rsp->data[0];
}
memset(evt, 0, sizeof(*evt));
@ -241,33 +273,6 @@ ipmi_sel_get_std_entry(struct ipmi_intf * intf, unsigned short id, struct sel_ev
return (rsp->data[1] << 8) | rsp->data[0];
}
static char *
ipmi_sel_timestamp(uint32_t stamp)
{
static unsigned char tbuf[40];
time_t s = (time_t)stamp;
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s));
return tbuf;
}
static char *
ipmi_sel_timestamp_date(uint32_t stamp)
{
static unsigned char tbuf[11];
time_t s = (time_t)stamp;
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y", localtime(&s));
return tbuf;
}
static char *
ipmi_sel_timestamp_time(uint32_t stamp)
{
static unsigned char tbuf[9];
time_t s = (time_t)stamp;
strftime(tbuf, sizeof(tbuf), "%H:%M:%S", localtime(&s));
return tbuf;
}
void
ipmi_sel_print_std_entry(struct sel_event_record * evt)
{
@ -330,9 +335,13 @@ ipmi_sel_print_std_entry(struct sel_event_record * evt)
printf(",");
else
printf(" | ");
ipmi_get_event_desc(evt, &description);
printf("%s\n", description ? description : "");
free(description);
if (description) {
printf("%s", description);
free(description);
}
printf("\n");
}
void
@ -396,7 +405,7 @@ ipmi_sel_list_entries(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned short reserve_id, next_id = 0;
unsigned short next_id = 0, curr_id = 0;
struct sel_event_record evt;
memset(&req, 0, sizeof(req));
@ -404,7 +413,9 @@ ipmi_sel_list_entries(struct ipmi_intf * intf)
req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return;
if (rsp->ccode) {
printf("Error: %x from Get SEL Info command\n",
rsp ? rsp->ccode : 0);
return;
@ -422,23 +433,26 @@ ipmi_sel_list_entries(struct ipmi_intf * intf)
req.msg.cmd = IPMI_CMD_RESERVE_SEL;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return;
if (rsp->ccode) {
printf("Error: %x from Reserve SEL command\n",
rsp ? rsp->ccode : 0);
return;
}
reserve_id = rsp->data[0] | rsp->data[1] << 8;
if (verbose)
printf("SEL Reservation ID: %04x\n", reserve_id);
while (next_id != 0xffff) {
curr_id = next_id;
if (verbose > 1)
printf("SEL Next ID: %04x\n", next_id);
printf("SEL Next ID: %04x\n", curr_id);
next_id = ipmi_sel_get_std_entry(intf, next_id, &evt);
if (!next_id)
break;
next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
if (!next_id) {
/* retry */
next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
if (!next_id)
break;
}
if (verbose)
ipmi_sel_print_std_entry_verbose(&evt);
@ -458,7 +472,9 @@ ipmi_sel_reserve(struct ipmi_intf * intf)
req.msg.cmd = IPMI_CMD_RESERVE_SEL;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return 0;
if (rsp->ccode) {
printf("Error:%x unable to reserve SEL\n",
rsp ? rsp->ccode : 0);
return 0;
@ -467,6 +483,108 @@ ipmi_sel_reserve(struct ipmi_intf * intf)
return rsp->data[0] | rsp->data[1] << 8;
}
/*
* ipmi_sel_get_time
*
* return 0 on success,
* -1 on error
*/
static int
ipmi_sel_get_time(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
static unsigned char tbuf[40];
time_t time;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = IPMI_GET_SEL_TIME;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get SEL Time Command\n", rsp ? rsp->ccode : 0);
return -1;
}
if (rsp->data_len != 4)
{
printf("Error:Invalid data length (0x%x) from Get SEL Time Command\n",
rsp->data_len);
return -1;
}
memcpy(&time, rsp->data, 4);
#if WORDS_BIGENDIAN
time = BSWAP_32(time);
#endif
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&time));
printf("%s\n", tbuf);
return 0;
}
/*
* ipmi_sel_set_time
*
* return 0 on success,
* -1 on error
*/
static int
ipmi_sel_set_time(struct ipmi_intf * intf, const char * time_string)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct tm tm;
time_t time;
const char * time_format = "%m/%d/%Y %H:%M:%S";
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = IPMI_SET_SEL_TIME;
req.msg.data = (unsigned char *)&time;
req.msg.data_len = sizeof(time);
/* Now how do we get our time_t from our ascii version? */
if (! strptime(time_string, time_format, &tm))
{
printf("Error. Specified time could not be parsed.\n");
return -1;
}
if ((time = mktime(&tm)) == 0xFFFFFFFF)
{
printf("Error. Specified time could not be parsed.\n");
return -1;
}
#if WORDS_BIGENDIAN
time = BSWAP_32(time);
#endif
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Set SEL Time Command\n", rsp ? rsp->ccode : 0);
return -1;
}
return 0;
}
static void
ipmi_sel_clear(struct ipmi_intf * intf)
{
@ -475,6 +593,8 @@ ipmi_sel_clear(struct ipmi_intf * intf)
unsigned short reserve_id;
unsigned char msg_data[6];
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
reserve_id = ipmi_sel_reserve(intf);
if (reserve_id == 0)
return;
@ -494,7 +614,9 @@ ipmi_sel_clear(struct ipmi_intf * intf)
req.msg.data_len = 6;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
if (!rsp)
return;
if (rsp->ccode) {
printf("Error:%x unable to clear SEL\n", rsp ? rsp->ccode : 0);
return;
}
@ -536,9 +658,12 @@ ipmi_sel_delete(struct ipmi_intf * intf, int argc, char ** argv)
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
if (!rsp)
{
printf("No response\n");
}
else if (rsp->ccode)
{
if (!rsp) printf("No response\n");
printf("Error %x unable to delete entry %d\n", rsp ? rsp->ccode : 0, id);
}
else
@ -563,6 +688,29 @@ int ipmi_sel_main(struct ipmi_intf * intf, int argc, char ** argv)
ipmi_sel_clear(intf);
else if (!strncmp(argv[0], "delete", 6))
ipmi_sel_delete(intf, argc-1, &argv[1]);
/*
* Get time
*/
else if (argc == 2 &&
!strncmp(argv[0], "get", 3) &&
!strncmp(argv[1], "time", 4))
{
ipmi_sel_get_time(intf);
}
/*
* Set time
*/
else if (argc == 3 &&
!strncmp(argv[0], "set", 3) &&
!strncmp(argv[1], "time", 4))
{
ipmi_sel_set_time(intf, argv[2]);
}
else
printf("Invalid SEL command: %s\n", argv[0]);
return 0;

View File

@ -38,104 +38,706 @@
#include <math.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_sensor.h>
extern int verbose;
#define READING_UNAVAILABLE 0x20
#define SCANNING_DISABLED 0x80
static void
ipmi_get_sensor_info_compact(struct ipmi_intf * intf,
struct sdr_record_compact_sensor * sensor)
static
struct ipmi_rs *
ipmi_sensor_get_sensor_thresholds(struct ipmi_intf * intf, unsigned char sensor)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = GET_SENSOR_THRESHOLDS;
req.msg.data = &sensor;
req.msg.data_len = sizeof(sensor);
rsp = intf->sendrecv(intf, &req);
return rsp;
}
static
struct ipmi_rs *
ipmi_sensor_set_sensor_thresholds(struct ipmi_intf * intf,
unsigned char sensor,
unsigned char threshold,
unsigned char setting)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
static struct sensor_set_thresh_rq set_thresh_rq;
memset(&set_thresh_rq, 0, sizeof(set_thresh_rq));
set_thresh_rq.sensor_num = sensor;
set_thresh_rq.set_mask = threshold;
if (threshold == UPPER_NON_RECOV_SPECIFIED)
set_thresh_rq.upper_non_recov = setting;
else if (threshold == UPPER_CRIT_SPECIFIED)
set_thresh_rq.upper_crit = setting;
else if (threshold == UPPER_NON_CRIT_SPECIFIED)
set_thresh_rq.upper_non_crit = setting;
else if (threshold == LOWER_NON_CRIT_SPECIFIED)
set_thresh_rq.lower_non_crit = setting;
else if (threshold == LOWER_CRIT_SPECIFIED)
set_thresh_rq.lower_crit = setting;
else if (threshold == LOWER_NON_RECOV_SPECIFIED)
set_thresh_rq.lower_non_recov = setting;
else
return NULL;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = SET_SENSOR_THRESHOLDS;
req.msg.data = (unsigned char *)&set_thresh_rq;
req.msg.data_len = sizeof(set_thresh_rq);
rsp = intf->sendrecv(intf, &req);
return rsp;
}
static void
ipmi_get_sensor_info_full(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
ipmi_sensor_print_full_discrete(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
{
char id[17];
char * unitstr = "discrete";
int validread=1;
unsigned char val = 0;
struct ipmi_rs * rsp;
char sval[16], unitstr[16], desc[17];
float val, tol;
unsigned raw_tol;
int i=0, not_available=0;
memset(desc, 0, sizeof(desc));
memcpy(desc, sensor->id_string, 16);
if (!sensor)
return;
memset(id, 0, sizeof(id));
memcpy(id, sensor->id_string, 16);
/*
* Get current reading
*/
rsp = ipmi_sdr_get_sensor_reading(intf, sensor->keys.sensor_num);
if ((rsp && (rsp->data[1] & READING_UNAVAILABLE)) ||
(rsp && !(rsp->data[1] & SCANNING_DISABLED)))
not_available = 1;
else {
memset(unitstr, 0, sizeof(unitstr));
/* determine units with possible modifiers */
switch (sensor->unit.modifier) {
case 2:
i += snprintf(unitstr, sizeof(unitstr), "%s * %s",
unit_desc[sensor->unit.type.base],
unit_desc[sensor->unit.type.modifier]);
break;
case 1:
i += snprintf(unitstr, sizeof(unitstr), "%s/%s",
unit_desc[sensor->unit.type.base],
unit_desc[sensor->unit.type.modifier]);
break;
case 0:
default:
i += snprintf(unitstr, sizeof(unitstr), "%s",
unit_desc[sensor->unit.type.base]);
break;
}
val = sdr_convert_sensor_reading(sensor, rsp->data[0]);
raw_tol = (sensor->mtol & 0x3f00) >> 8;
tol = sdr_convert_sensor_reading(sensor, raw_tol * 2);
if (!rsp)
{
printf("Error reading sensor %s (#%02x)\n", id, sensor->keys.sensor_num);
return;
}
else if (rsp->ccode || (rsp->data[1] & READING_UNAVAILABLE))
{
validread = 0;
}
else
{
/* convert RAW reading into units */
val = rsp->data[0];
}
if (!verbose) {
/*
* print sensor name, reading, state
*/
printf("%-16s | ", sensor->id_code ? desc : NULL);
if (csv_output)
{
}
else
{
if (!verbose)
{
/* output format
* id value units status thresholds....
*/
printf("%-16s ", id);
if (validread)
{
printf("| 0x%-8x | %-10s | 0x%02x%02x",
val,
unitstr,
rsp->data[2],
rsp->data[3]);
}
else
{
printf("| %-10s | %-10s | %-6s",
"na",
unitstr,
"na");
}
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
i = 0;
memset(sval, 0, sizeof(sval));
if (not_available) {
i += snprintf(sval, sizeof(sval), "no reading ");
} else {
i += snprintf(sval, sizeof(sval), "%.*f %s", (val==(int)val) ? 0 : 3, val, unitstr);
printf("\n");
}
printf("%s", sval);
i--;
for (; i<sizeof(sval); i++)
printf(" ");
printf(" | ");
printf("%s", ipmi_sdr_get_status(rsp->data[2]));
printf("\n");
} else {
printf("Sensor ID : %s (0x%x)\n", desc, sensor->keys.sensor_num);
if (not_available)
printf("Sensor Reading : Unavailable");
else
printf("Sensor Reading : %.*f (+/- %.*f) %s\n",
(val==(int)val) ? 0 : 3,
val,
(tol==(int)tol) ? 0 : 3,
tol,
unitstr);
printf("\n");
{
printf("Sensor ID : %s (0x%x)\n",
id, sensor->keys.sensor_num);
printf("Sensor Type (Discrete) : %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.type));
printf("Sensor Reading : ");
if (validread)
{
printf("0x%x\n", val);
}
else
{
printf("not present\n\n");
return;
}
printf("States Asserted : ");
if (!rsp->data[2] && !rsp->data[3])
printf("none");
else
{
if (rsp->data[2] & STATE_0_ASSERTED)
printf("%d ", 0);
if (rsp->data[2] & STATE_1_ASSERTED)
printf("%d ", 1);
if (rsp->data[2] & STATE_2_ASSERTED)
printf("%d ", 2);
if (rsp->data[2] & STATE_3_ASSERTED)
printf("%d ", 3);
if (rsp->data[2] & STATE_4_ASSERTED)
printf("%d ", 4);
if (rsp->data[2] & STATE_5_ASSERTED)
printf("%d ", 5);
if (rsp->data[2] & STATE_6_ASSERTED)
printf("%d ", 6);
if (rsp->data[2] & STATE_7_ASSERTED)
printf("%d ", 7);
if (rsp->data[3] & STATE_8_ASSERTED)
printf("%d ", 8);
if (rsp->data[3] & STATE_9_ASSERTED)
printf("%d ", 9);
if (rsp->data[3] & STATE_10_ASSERTED)
printf("%d ", 10);
if (rsp->data[3] & STATE_11_ASSERTED)
printf("%d ", 11);
if (rsp->data[3] & STATE_12_ASSERTED)
printf("%d ", 12);
if (rsp->data[3] & STATE_13_ASSERTED)
printf("%d ", 13);
if (rsp->data[3] & STATE_14_ASSERTED)
printf("%d ", 14);
}
printf("\n\n");
}
}
}
static void
ipmi_sensor_print_full_analog(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
{
char unitstr[16], id[17];
int i=0, validread=1, thresh_available = 1;
float val = 0.0;
struct ipmi_rs * rsp;
char * status = NULL;
if (!sensor)
return;
/* only handle linear sensors (for now) */
if (sensor->linearization) {
printf("non-linear!\n");
return;
}
memset(id, 0, sizeof(id));
memcpy(id, sensor->id_string, 16);
/*
* Get current reading
*/
rsp = ipmi_sdr_get_sensor_reading(intf, sensor->keys.sensor_num);
if (!rsp)
{
printf("Error reading sensor %s (#%02x)\n", id, sensor->keys.sensor_num);
return;
}
else if (rsp->ccode || (rsp->data[1] & READING_UNAVAILABLE))
{
validread = 0;
}
else
{
/* convert RAW reading into units */
val = rsp->data[0] ? sdr_convert_sensor_reading(sensor, rsp->data[0]) : 0;
status = (char*)ipmi_sdr_get_status(rsp->data[2]);
}
/*
* Figure out units
*/
memset(unitstr, 0, sizeof(unitstr));
switch (sensor->unit.modifier)
{
case 2:
i += snprintf(unitstr, sizeof(unitstr), "%s * %s",
unit_desc[sensor->unit.type.base],
unit_desc[sensor->unit.type.modifier]);
break;
case 1:
i += snprintf(unitstr, sizeof(unitstr), "%s/%s",
unit_desc[sensor->unit.type.base],
unit_desc[sensor->unit.type.modifier]);
break;
case 0:
default:
i += snprintf(unitstr, sizeof(unitstr), "%s",
unit_desc[sensor->unit.type.base]);
break;
}
/*
* Get sensor thresholds
*/
rsp = ipmi_sensor_get_sensor_thresholds(intf, sensor->keys.sensor_num);
if (!rsp)
thresh_available = 0;
if (csv_output)
{
}
else
{
if (!verbose)
{
/* output format
* id value units status thresholds....
*/
printf("%-16s ", id);
if (validread)
{
printf("| %-10.3f | %-10s | %-6s",
val,
unitstr,
status ? : "");
}
else
{
printf("| %-10s | %-10s | %-6s",
"na",
unitstr,
"na");
}
if (thresh_available)
{
if (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[3]));
else
printf("| %-10s", "na");
if (rsp->data[0] & LOWER_CRIT_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[2]));
else
printf("| %-10s", "na");
if (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[1]));
else
printf("| %-10s", "na");
if (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[4]));
else
printf("| %-10s", "na");
if (rsp->data[0] & UPPER_CRIT_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[5]));
else
printf("| %-10s", "na");
if (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)
printf("| %-10.3f", sdr_convert_sensor_reading(sensor, rsp->data[6]));
else
printf("| %-10s", "na");
}
else
{
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
}
printf("\n");
}
else
{
printf("Sensor ID : %s (0x%x)\n",
id, sensor->keys.sensor_num);
printf("Sensor Type (Analog) : %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.type));
printf("Sensor Reading : ");
if (validread) {
#if WORDS_BIGENDIAN
unsigned raw_tol = sensor->mtol & 0x3f;
#else
unsigned raw_tol = (sensor->mtol & 0x3f00) >> 8;
#endif
float tol = sdr_convert_sensor_reading(sensor, raw_tol * 2);
printf("%.*f (+/- %.*f) %s\n",
(val==(int)val) ? 0 : 3,
val,
(tol==(int)tol) ? 0 : 3,
tol,
unitstr);
printf("Status : %s\n", status ? : "");
if (thresh_available)
{
if (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)
printf("Lower Non-Recoverable : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[3]));
else
printf("Lower Non-Recoverable : na\n");
if (rsp->data[0] & LOWER_CRIT_SPECIFIED)
printf("Lower Critical : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[2]));
else
printf("Lower Critical : na\n");
if (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)
printf("Lower Non-Critical : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[1]));
else
printf("Lower Non-Critical : na\n");
if (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)
printf("Upper Non-Critical : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[4]));
else
printf("Upper Non-Critical : na\n");
if (rsp->data[0] & UPPER_CRIT_SPECIFIED)
printf("Upper Critical : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[5]));
else
printf("Upper Critical : na\n");
if (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)
printf("Upper Non-Recoverable : %.3f\n",
sdr_convert_sensor_reading(sensor, rsp->data[6]));
else
printf("Upper Non-Recoverable : na\n");
}
} else
printf("not present\n");
printf("\n");
}
}
}
void ipmi_sensor_print_full(struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor)
{
if (sensor->unit.analog != 3)
ipmi_sensor_print_full_analog(intf, sensor);
else
ipmi_sensor_print_full_discrete(intf, sensor);
}
void ipmi_sensor_print_compact(struct ipmi_intf * intf,
struct sdr_record_compact_sensor * sensor)
{
char id[17];
char * unitstr = "discrete";
int validread=1;
unsigned char val = 0;
struct ipmi_rs * rsp;
if (!sensor)
return;
memset(id, 0, sizeof(id));
memcpy(id, sensor->id_string, 16);
/*
* Get current reading
*/
rsp = ipmi_sdr_get_sensor_reading(intf, sensor->keys.sensor_num);
if (!rsp)
{
printf("Error reading sensor %s (#%02x)\n", id, sensor->keys.sensor_num);
return;
}
else if (rsp->ccode || (rsp->data[1] & READING_UNAVAILABLE))
{
validread = 0;
}
else
{
/* convert RAW reading into units */
val = rsp->data[0];
}
if (csv_output)
{
}
else
{
if (!verbose)
{
/* output format
* id value units status thresholds....
*/
printf("%-16s ", id);
if (validread)
{
printf("| 0x%-8x | %-10s | 0x%02x%02x",
val,
unitstr,
rsp->data[2],
rsp->data[3]);
}
else
{
printf("| %-10s | %-10s | %-6s",
"na",
unitstr,
"na");
}
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
printf("\n");
}
else
{
printf("Sensor ID : %s (0x%x)\n",
id, sensor->keys.sensor_num);
printf("Sensor Type (Discrete) : %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.type));
printf("Sensor Reading : ");
if (validread)
{
printf("0x%04x\n", val);
}
else
{
printf("not present\n\n");
return;
}
printf("States Asserted : ");
if (!rsp->data[2] && !rsp->data[3])
printf("none");
else
{
if (rsp->data[2] & STATE_0_ASSERTED)
printf("%d ", 0);
if (rsp->data[2] & STATE_1_ASSERTED)
printf("%d ", 1);
if (rsp->data[2] & STATE_2_ASSERTED)
printf("%d ", 2);
if (rsp->data[2] & STATE_3_ASSERTED)
printf("%d ", 3);
if (rsp->data[2] & STATE_4_ASSERTED)
printf("%d ", 4);
if (rsp->data[2] & STATE_5_ASSERTED)
printf("%d ", 5);
if (rsp->data[2] & STATE_6_ASSERTED)
printf("%d ", 6);
if (rsp->data[2] & STATE_7_ASSERTED)
printf("%d ", 7);
if (rsp->data[3] & STATE_8_ASSERTED)
printf("%d ", 8);
if (rsp->data[3] & STATE_9_ASSERTED)
printf("%d ", 9);
if (rsp->data[3] & STATE_10_ASSERTED)
printf("%d ", 10);
if (rsp->data[3] & STATE_11_ASSERTED)
printf("%d ", 11);
if (rsp->data[3] & STATE_12_ASSERTED)
printf("%d ", 12);
if (rsp->data[3] & STATE_13_ASSERTED)
printf("%d ", 13);
if (rsp->data[3] & STATE_14_ASSERTED)
printf("%d ", 14);
}
printf("\n\n");
}
}
}
static void
ipmi_sensor_list(struct ipmi_intf * intf)
{
ipmi_sdr_print_sdr(intf, 0xff);
struct sdr_get_rs * header;
struct ipmi_sdr_iterator * itr;
if (verbose > 1)
printf("Querying SDR for sensor list\n");
itr = ipmi_sdr_start(intf);
if (!itr)
{
printf("Unable to open SDRR for reading\n");
return;
}
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL)
{
unsigned char * rec = ipmi_sdr_get_record(intf, header, itr);
if (!rec)
continue;
switch(header->type)
{
case SDR_RECORD_TYPE_FULL_SENSOR:
ipmi_sensor_print_full(intf, (struct sdr_record_full_sensor *) rec);
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
ipmi_sensor_print_compact(intf, (struct sdr_record_compact_sensor *) rec);
break;
}
free(rec);
}
ipmi_sdr_end(intf, itr);
}
const struct valstr threshold_vals[] = {
{ UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable" },
{ UPPER_CRIT_SPECIFIED, "Upper Critical" },
{ UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical" },
{ LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable" },
{ LOWER_CRIT_SPECIFIED, "Lower Critical" },
{ LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical" },
{ 0x00, NULL },
};
static void
ipmi_sensor_set_threshold(struct ipmi_intf * intf, int argc, char ** argv)
{
char * id,
* thresh;
unsigned char settingMask;
float setting;
struct sdr_record_list * sdr;
struct ipmi_rs * rsp;
if (argc < 3 || !strncmp(argv[0], "help", 4))
{
printf("sensor thresh <id> <threshold> <setting>\n");
printf(" id : name of the sensor for which threshold is to be set\n");
printf(" threshold : which threshold to set\n");
printf(" unr = upper non-recoverable\n");
printf(" ucr = upper critical\n");
printf(" unc = upper non-critical\n");
printf(" lnc = lower non-critical\n");
printf(" lcr = lower critical\n");
printf(" lnr = lower non-recoverable\n");
printf(" setting : the value to set the threshold to\n");
return;
}
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
id = argv[0];
thresh = argv[1];
setting = (float)atof(argv[2]);
if (!strcmp(thresh, "unr"))
{
settingMask = UPPER_NON_RECOV_SPECIFIED;
}
else if (!strcmp(thresh, "ucr"))
{
settingMask = UPPER_CRIT_SPECIFIED;
}
else if (!strcmp(thresh, "unc"))
{
settingMask = UPPER_NON_CRIT_SPECIFIED;
}
else if (!strcmp(thresh, "lnc"))
{
settingMask = LOWER_NON_CRIT_SPECIFIED;
}
else if (!strcmp(thresh, "lcr"))
{
settingMask = LOWER_CRIT_SPECIFIED;
}
else if (!strcmp(thresh, "lnr"))
{
settingMask = LOWER_NON_RECOV_SPECIFIED;
}
else
{
printf("Valid threshold not specified!\n");
return;
}
printf("Locating sensor record...\n");
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (sdr)
{
if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR)
{
printf("Invalid sensor type %02x\n", sdr->type);
}
else
{
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string, val2str(settingMask, threshold_vals), setting);
rsp = ipmi_sensor_set_sensor_thresholds(intf,
sdr->record.full->keys.sensor_num, settingMask,
sdr_convert_sensor_value_to_raw(sdr->record.full, setting));
if (rsp && rsp->ccode)
printf("Error setting threshold: 0x%x\n", rsp->ccode);
}
}
else
{
printf("Sensor data record not found!\n");
}
ipmi_sdr_list_empty(intf);
}
static void ipmi_sensor_get(struct ipmi_intf * intf, int argc, char ** argv)
{
struct sdr_record_list * sdr;
int i;
if (argc < 1 || !strncmp(argv[0], "help", 4)) {
printf("sensor get <id> ... [id]\n");
printf(" id : name of desired sensor\n");
return;
}
printf("Locating sensor record...\n");
/* lookup by sensor name */
for (i=0; i<argc; i++) {
sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
if (sdr) {
verbose = verbose ? : 1;
switch (sdr->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
ipmi_sensor_print_full(intf, sdr->record.full);
break;
case SDR_RECORD_TYPE_COMPACT_SENSOR:
ipmi_sensor_print_compact(intf, sdr->record.compact);
break;
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
ipmi_sdr_print_sensor_eventonly(intf, sdr->record.eventonly);
break;
case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
ipmi_sdr_print_fru_locator(intf, sdr->record.fruloc);
break;
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
ipmi_sdr_print_mc_locator(intf, sdr->record.mcloc);
break;
}
} else {
printf("Sensor data record \"%s\" not found!\n", argv[i]);
}
}
ipmi_sdr_list_empty(intf);
}
int
@ -144,11 +746,17 @@ ipmi_sensor_main(struct ipmi_intf * intf, int argc, char ** argv)
if (!argc)
ipmi_sensor_list(intf);
else if (!strncmp(argv[0], "help", 4)) {
printf("Sensor Commands: list\n");
printf("Sensor Commands: list thresh get\n");
}
else if (!strncmp(argv[0], "list", 4)) {
ipmi_sensor_list(intf);
}
else if (!strncmp(argv[0], "thresh", 5)) {
ipmi_sensor_set_threshold(intf, argc-1, &argv[1]);
}
else if (!strncmp(argv[0], "get", 3)) {
ipmi_sensor_get(intf, argc-1, &argv[1]);
}
else
printf("Invalid sensor command: %s\n", argv[0]);
return 0;

440
ipmitool/lib/ipmi_session.c Normal file
View File

@ -0,0 +1,440 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_session.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/bswap.h>
typedef enum {
IPMI_SESSION_REQUEST_CURRENT = 0,
IPMI_SESSION_REQUEST_ALL,
IPMI_SESSION_REQUEST_BY_ID,
IPMI_SESSION_REQUEST_BY_HANDLE
} Ipmi_Session_Request_Type;
/*
* print_session_info_csv
*/
static void
print_session_info_csv(const struct get_session_info_rsp * session_info,
int data_len)
{
char buffer[18];
uint16_t console_port_tmp;
printf("%d", session_info->session_handle);
printf(",%d", session_info->session_slot_count);
printf(",%d", session_info->active_session_count);
if (data_len == 3)
{
/* There is no session data here*/
printf("\n");
return;
}
printf(",%d", session_info->user_id);
printf(",%s", val2str(session_info->privilege_level, ipmi_privlvl_vals));
printf(",%s", session_info->auxiliary_data?
"IPMIv2/RMCP+" : "IPMIv1.5");
printf(",0x%02x", session_info->channel_number);
if (data_len == 18)
{
/* We have 802.3 LAN data */
printf(",%s",
inet_ntop(AF_INET,
&(session_info->channel_data.lan_data.console_ip),
buffer,
16));
printf(",%02x:%02x:%02x:%02x:%02x:%02x",
session_info->channel_data.lan_data.console_mac[0],
session_info->channel_data.lan_data.console_mac[1],
session_info->channel_data.lan_data.console_mac[2],
session_info->channel_data.lan_data.console_mac[3],
session_info->channel_data.lan_data.console_mac[4],
session_info->channel_data.lan_data.console_mac[5]);
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf(",%d", console_port_tmp);
}
else if ((data_len == 12) || (data_len == 14))
{
/* Channel async serial/modem */
printf(",%s",
val2str(session_info->channel_data.modem_data.session_channel_activity_type,
ipmi_channel_activity_type_vals));
printf(",%d",
session_info->channel_data.modem_data.destination_selector);
printf(",%s",
inet_ntop(AF_INET,
&(session_info->channel_data.modem_data.console_ip),
buffer,
16));
if (data_len == 14)
{
/* Connection is PPP */
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf(",%d", console_port_tmp);
}
}
printf("\n");
}
/*
* print_session_info_verbose
*/
static void
print_session_info_verbose(const struct get_session_info_rsp * session_info,
int data_len)
{
char buffer[18];
uint16_t console_port_tmp;
printf("session handle : %d\n", session_info->session_handle);
printf("slot count : %d\n", session_info->session_slot_count);
printf("active sessions : %d\n", session_info->active_session_count);
if (data_len == 3)
{
/* There is no session data here */
printf("\n");
return;
}
printf("user id : %d\n", session_info->user_id);
printf("privilege level : %s\n",
val2str(session_info->privilege_level, ipmi_privlvl_vals));
printf("session type : %s\n", session_info->auxiliary_data?
"IPMIv2/RMCP+" : "IPMIv1.5");
printf("channel number : 0x%02x\n", session_info->channel_number);
if (data_len == 18)
{
/* We have 802.3 LAN data */
printf("console ip : %s\n",
inet_ntop(AF_INET,
&(session_info->channel_data.lan_data.console_ip),
buffer,
16));
printf("console mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
session_info->channel_data.lan_data.console_mac[0],
session_info->channel_data.lan_data.console_mac[1],
session_info->channel_data.lan_data.console_mac[2],
session_info->channel_data.lan_data.console_mac[3],
session_info->channel_data.lan_data.console_mac[4],
session_info->channel_data.lan_data.console_mac[5]);
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf("console port : %d\n", console_port_tmp);
}
else if ((data_len == 12) || (data_len == 14))
{
/* Channel async serial/modem */
printf("Session/Channel Activity Type : %s\n",
val2str(session_info->channel_data.modem_data.session_channel_activity_type,
ipmi_channel_activity_type_vals));
printf("Destination selector : %d\n",
session_info->channel_data.modem_data.destination_selector);
printf("console ip : %s\n",
inet_ntop(AF_INET,
&(session_info->channel_data.modem_data.console_ip),
buffer,
16));
if (data_len == 14)
{
/* Connection is PPP */
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf("console port : %d\n", console_port_tmp);
}
}
printf("\n");
}
static void print_session_info(const struct get_session_info_rsp * session_info,
int data_len)
{
if (csv_output)
print_session_info_csv(session_info, data_len);
else
print_session_info_verbose(session_info, data_len);
}
/*
* ipmi_get_session_info
*
* returns 0 on success
* -1 on error
*/
int
ipmi_get_session_info(struct ipmi_intf * intf,
Ipmi_Session_Request_Type session_request_type,
uint32_t id_or_handle)
{
int i, retval = 0;
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[5]; // max length of the variable length request
struct get_session_info_rsp session_info;
memset(&req, 0, sizeof(req));
memset(&session_info, 0, sizeof(session_info));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_SESSION_INFO; // 0x3D
req.msg.data = rqdata;
switch (session_request_type)
{
case IPMI_SESSION_REQUEST_CURRENT:
case IPMI_SESSION_REQUEST_BY_ID:
case IPMI_SESSION_REQUEST_BY_HANDLE:
switch (session_request_type)
{
case IPMI_SESSION_REQUEST_CURRENT:
rqdata[0] = 0x00;
req.msg.data_len = 1;
break;
case IPMI_SESSION_REQUEST_BY_ID:
rqdata[0] = 0xFF;
rqdata[1] = id_or_handle & 0x000000FF;
rqdata[2] = (id_or_handle >> 8) & 0x000000FF;
rqdata[3] = (id_or_handle >> 16) & 0x000000FF;
rqdata[4] = (id_or_handle >> 24) & 0x000000FF;
req.msg.data_len = 5;
break;
case IPMI_SESSION_REQUEST_BY_HANDLE:
rqdata[0] = 0xFE;
rqdata[1] = (unsigned char)id_or_handle;
req.msg.data_len = 2;
break;
case IPMI_SESSION_REQUEST_ALL:
break;
}
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get Session Info Command\n", rsp ? rsp->ccode : 0);
if ((session_request_type == IPMI_SESSION_REQUEST_CURRENT) &&
(strncmp(intf->name, "intf_lan", 8)))
printf("It is likely that the channel in use does not support sessions\n");
retval = -1;
}
else
{
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
}
break;
case IPMI_SESSION_REQUEST_ALL:
req.msg.data_len = 1;
i = 1;
do
{
rqdata[0] = i++;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode || (rsp->data_len < 3))
{
if (!rsp || (rsp->ccode != 0xCC))
{
printf("Error:%x Get Session Info Command\n", rsp ? rsp->ccode : 0);
retval = -1;
}
break;
}
else
{
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
}
} while (i <= session_info.session_slot_count);
break;
}
return retval;
}
void
printf_session_usage()
{
printf("Session Commands: info <active | all | id 0xnnnnnnnn | handle 0xnn>\n");
}
int
ipmi_session_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
if (!argc || !strncmp(argv[0], "help", 4))
{
printf_session_usage();
retval = 1;
}
else if (!strncmp(argv[0], "info", 4))
{
if ((argc < 2) || !strncmp(argv[1], "help", 4))
{
printf_session_usage();
retval = 1;
}
else
{
Ipmi_Session_Request_Type session_request_type = 0;
uint32_t id_or_handle = 0;
if (!strncmp(argv[1], "active", 6))
session_request_type = IPMI_SESSION_REQUEST_CURRENT;
else if (!strncmp(argv[1], "all", 3))
session_request_type = IPMI_SESSION_REQUEST_ALL;
else if (!strncmp(argv[1], "id", 2))
{
if (argc >= 3)
{
session_request_type = IPMI_SESSION_REQUEST_BY_ID;
id_or_handle = strtol(argv[2], NULL, 16);
}
else
{
printf("Missing id argument\n");
printf_session_usage();
retval = 1;
}
}
else if (!strncmp(argv[1], "handle", 6))
{
if (argc >= 3)
{
session_request_type = IPMI_SESSION_REQUEST_BY_HANDLE;
id_or_handle = strtol(argv[2], NULL, 16);
}
else
{
printf("Missing handle argument\n");
printf_session_usage();
retval = 1;
}
}
else
{
printf("Invalid SESSION info parameter: %s\n", argv[1]);
printf_session_usage();
retval = 1;
}
if (! retval)
retval = ipmi_get_session_info(intf,
session_request_type,
id_or_handle);
}
}
else
{
printf("Invalid SESSION command: %s\n", argv[0]);
printf_session_usage();
retval = 1;
}
return retval;
}

File diff suppressed because it is too large Load Diff

101
ipmitool/lib/ipmi_strings.c Normal file
View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stddef.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_constants.h>
const struct valstr ipmi_channel_activity_type_vals[] = {
{ 0, "IPMI Messaging session active" },
{ 1, "Callback Messaging session active" },
{ 2, "Dial-out Alert active" },
{ 3, "TAP Page Active" },
{ 0x00, NULL },
};
/*
* From table 26-4 of the IPMI v2 specification
*/
const struct valstr impi_bit_rate_vals[] = {
{ 0x00, "IPMI-Over-Serial-Setting"}, /* Using the value in the IPMI Over Serial Config */
{ 0x06, "9.6" },
{ 0x07, "19.2" },
{ 0x08, "38.4" },
{ 0x09, "57.6" },
{ 0x0A, "115.2" },
{ 0x00, NULL },
};
const struct valstr ipmi_privlvl_vals[] = {
{ IPMI_SESSION_PRIV_CALLBACK, "CALLBACK" },
{ IPMI_SESSION_PRIV_USER, "USER" },
{ IPMI_SESSION_PRIV_OPERATOR, "OPERATOR" },
{ IPMI_SESSION_PRIV_ADMIN, "ADMINISTRATOR" },
{ IPMI_SESSION_PRIV_OEM, "OEM" },
{ 0xF, "NO ACCESS" },
{ 0, NULL },
};
const struct valstr ipmi_set_in_progress_vals[] = {
{ IPMI_SET_IN_PROGRESS_SET_COMPLETE, "set-complete" },
{ IPMI_SET_IN_PROGRESS_IN_PROGRESS, "set-in-progress" },
{ IPMI_SET_IN_PROGRESS_COMMIT_WRITE, "commit-write" },
{ 0, NULL },
};
const struct valstr ipmi_authtype_session_vals[] = {
{ IPMI_SESSION_AUTHTYPE_NONE, "NONE" },
{ IPMI_SESSION_AUTHTYPE_MD2, "MD2" },
{ IPMI_SESSION_AUTHTYPE_MD5, "MD5" },
{ IPMI_SESSION_AUTHTYPE_PASSWORD, "PASSWORD" },
{ IPMI_SESSION_AUTHTYPE_OEM, "OEM" },
{ 0, NULL },
};
const struct valstr ipmi_authtype_vals[] = {
{ IPMI_1_5_AUTH_TYPE_BIT_NONE, "NONE" },
{ IPMI_1_5_AUTH_TYPE_BIT_MD2, "MD2" },
{ IPMI_1_5_AUTH_TYPE_BIT_MD5, "MD5" },
{ IPMI_1_5_AUTH_TYPE_BIT_PASSWORD, "PASSWORD" },
{ IPMI_1_5_AUTH_TYPE_BIT_OEM, "OEM" },
{ 0, NULL },
};

722
ipmitool/lib/ipmi_user.c Normal file
View File

@ -0,0 +1,722 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_user.h>
#include <ipmitool/ipmi_constants.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/bswap.h>
extern int verbose;
extern int csv_output;
#define IPMI_PASSWORD_DISABLE_USER 0x00
#define IPMI_PASSWORD_ENABLE_USER 0x01
#define IPMI_PASSWORD_SET_PASSWORD 0x02
#define IPMI_PASSWORD_TEST_PASSWORD 0x03
/*
* ipmi_get_user_access
*
* param intf [in]
* param channel_number [in]
* param user_id [in]
* param user_access [out]
*
* return 0 on succes
* 1 on failure
*/
static int
ipmi_get_user_access(
struct ipmi_intf * intf,
unsigned char channel_number,
unsigned char user_id,
struct user_access_rsp * user_access)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char msg_data[2];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_GET_USER_ACCESS; /* 0x44 */
req.msg.data = msg_data;
req.msg.data_len = 2;
/* The channel number will remain constant throughout this function */
msg_data[0] = channel_number;
msg_data[1] = user_id;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
printf("Error:%x Get User Access Command (user 0x%x)\n",
rsp ? rsp->ccode : 0, msg_data[1]);
return -1;
}
memcpy(user_access,
rsp->data,
sizeof(struct user_access_rsp));
return 0;
}
/*
* ipmi_get_user_name
*
* param intf [in]
* param channel_number [in]
* param user_id [in]
* param user_name [out]
*
* return 0 on succes
* 1 on failure
*/
static int
ipmi_get_user_name(
struct ipmi_intf * intf,
unsigned char user_id,
char * user_name)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char msg_data[1];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_GET_USER_NAME; /* 0x45 */
req.msg.data = msg_data;
req.msg.data_len = 1;
msg_data[0] = user_id;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
printf("Error:%x Get User Name Command (user 0x%x)\n",
rsp ? rsp->ccode : 0, msg_data[0]);
return -1;
}
memcpy(user_name, rsp->data, 16);
return 0;
}
static void
dump_user_access(
unsigned char user_id,
const char * user_name,
struct user_access_rsp * user_access)
{
static int printed_header = 0;
if (! printed_header)
{
printf("ID Name Callin Link Auth IPMI Msg "
"Channel Priv Limit\n");
printed_header = 1;
}
printf("%-4d%-17s%-8s%-11s%-11s%-s\n",
user_id,
user_name,
user_access->no_callin_access? "false": "true ",
user_access->link_auth_access? "true ": "false",
user_access->ipmi_messaging_access? "true ": "false",
val2str(user_access->channel_privilege_limit,
ipmi_privlvl_vals));
}
static void
dump_user_access_csv(
unsigned char user_id,
const char * user_name,
struct user_access_rsp * user_access)
{
printf("%d,%s,%s,%s,%s,%s\n",
user_id,
user_name,
user_access->no_callin_access? "false": "true",
user_access->link_auth_access? "true": "false",
user_access->ipmi_messaging_access? "true": "false",
val2str(user_access->channel_privilege_limit,
ipmi_privlvl_vals));
}
static int
ipmi_print_user_list(
struct ipmi_intf * intf,
unsigned char channel_number)
{
/* This is where you were! */
char user_name[17];
struct user_access_rsp user_access;
unsigned char current_user_id = 1;
do
{
if (ipmi_get_user_access(intf,
channel_number,
current_user_id,
&user_access))
return -1;
if (ipmi_get_user_name(intf,
current_user_id,
user_name))
return -1;
if ((current_user_id == 0) ||
user_access.link_auth_access ||
user_access.ipmi_messaging_access ||
strcmp("", user_name))
{
if (csv_output)
dump_user_access_csv(current_user_id,
user_name, &user_access);
else
dump_user_access(current_user_id,
user_name,
&user_access);
}
++current_user_id;
} while((current_user_id < user_access.maximum_ids) &&
(current_user_id < 63)); /* Absolute maximum allowed by spec */
return 0;
}
static int
ipmi_print_user_summary(
struct ipmi_intf * intf,
unsigned char channel_number)
{
struct user_access_rsp user_access;
if (ipmi_get_user_access(intf,
channel_number,
1,
&user_access))
return -1;
if (csv_output)
{
printf("%d,%d,%d\n",
user_access.maximum_ids,
user_access.enabled_user_count,
user_access.fixed_name_count);
}
else
{
printf("Maximum IDs : %d\n",
user_access.maximum_ids);
printf("Enabled User Count : %d\n",
user_access.enabled_user_count);
printf("Fixed Name Count : %d\n",
user_access.fixed_name_count);
}
return 0;
}
/*
* ipmi_user_set_username
*/
static int
ipmi_user_set_username(
struct ipmi_intf * intf,
unsigned char user_id,
const char * name)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char msg_data[17];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_SET_USER_NAME; /* 0x45 */
req.msg.data = msg_data;
req.msg.data_len = 17;
/* The channel number will remain constant throughout this function */
msg_data[0] = user_id;
memset(msg_data + 1, 0, 16);
strcpy(msg_data + 1, name);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
printf("Error:%x Set User Name Command\n",
rsp ? rsp->ccode : 0);
return -1;
}
return 0;
}
/*
* ipmi_user_set_password
*
* This function is responsible for 4 things
* Enabling/Disabling users
* Setting/Testing passwords
*/
static int
ipmi_user_set_password(
struct ipmi_intf * intf,
unsigned char user_id,
unsigned char operation,
const char * password,
int is_twenty_byte_password)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
char * msg_data;
int ret = 0;
int password_length = (is_twenty_byte_password? 20 : 16);
msg_data = (char*)malloc(password_length + 2);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_SET_USER_PASSWORD; /* 0x47 */
req.msg.data = msg_data;
req.msg.data_len = password_length + 2;
/* The channel number will remain constant throughout this function */
msg_data[0] = user_id;
if (is_twenty_byte_password)
msg_data[0] |= 0x80;
msg_data[1] = operation;
memset(msg_data + 2, 0, password_length);
if (password)
strncpy(msg_data + 2, password, password_length);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode)
{
printf("Error:%x Set User Password Command\n",
rsp ? rsp->ccode : 0);
ret = (rsp? rsp->ccode : -1);
}
return ret;
}
/*
* ipmi_user_test_password
*
* Call ipmi_user_set_password, and interpret the result
*/
static int
ipmi_user_test_password(
struct ipmi_intf * intf,
unsigned char user_id,
const char * password,
int is_twenty_byte_password)
{
int ret;
ret = ipmi_user_set_password(intf,
user_id,
IPMI_PASSWORD_TEST_PASSWORD,
password,
is_twenty_byte_password);
if (! ret)
printf("Success\n");
else if (ret == 0x80)
printf("Failure: password incorrect\n");
else if (ret == 0x81)
printf("Failure: wrong password size\n");
else
printf("Unknown error\n");
return (ret ? -1 : 0);
}
/*
* print_user_usage
*/
void
print_user_usage()
{
printf("\n");
printf("User Commands: summary [<channel number>]\n");
printf(" list [<channel number>]\n");
printf(" set name <user id> <username>\n");
printf(" set password <user id> [<password>]\n");
printf(" disable <user id> [<channel number>]\n");
printf(" enable <user id> [<channel number>]\n");
printf(" test <user id> <16|20> [<password]>\n");
printf("\n");
}
const char *
ipmi_user_build_password_prompt(unsigned char user_id)
{
static char prompt[128];
sprintf(prompt, "Password for user %d: ", user_id);
return prompt;
}
/*
* ipmi_user_main
*
* Upon entry to this function argv should contain our arguments
* specific to this subcommand
*/
int
ipmi_user_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
/*
* Help
*/
if (!argc || !strncmp(argv[0], "help", 4))
print_user_usage();
/*
* Summary
*/
else if (!strncmp(argv[0], "summary", 7)) {
unsigned char channel;
if (argc == 1)
channel = 0x0E; /* Ask about the current channel */
else if (argc == 2)
channel = (unsigned char)strtol(argv[1], NULL, 0);
else
{
print_user_usage();
return -1;
}
retval = ipmi_print_user_summary(intf, channel);
}
/*
* List
*/
else if (!strncmp(argv[0], "list", 4)) {
unsigned char channel;
if (argc == 1)
channel = 0x0E; /* Ask about the current channel */
else if (argc == 2)
channel = (unsigned char)strtol(argv[1], NULL, 0);
else
{
print_user_usage();
return -1;
}
retval = ipmi_print_user_list(intf, channel);
}
/*
* Test
*/
else if (!strncmp(argv[0], "test", 4))
{
// a little fucking irritating, isn't it
if ((argc == 3 || argc == 4) &&
((!strncmp(argv[2], "16", 2)) ||
(!strncmp(argv[2], "20", 2))))
{
char * password = NULL;
int password_length = atoi(argv[2]);
unsigned char user_id = (unsigned char)strtol(argv[1],
NULL,
0);
if (! user_id)
{
printf("Error. Invalid user ID: %d\n", user_id);
return -1;
}
if (argc == 3)
{
/* We need to prompt for a password */
char * tmp;
const char * password_prompt =
ipmi_user_build_password_prompt(user_id);
#ifdef HAVE_GETPASSPHRASE
if ((tmp = getpassphrase (password_prompt)))
#else
if ((tmp = (char*)getpass(password_prompt)))
#endif
{
password = strdup(tmp);
}
}
else
password = argv[3];
retval = ipmi_user_test_password(intf,
user_id,
password,
password_length == 20);
}
else
{
print_user_usage();
return -1;
}
}
/*
* Set
*/
else if (!strncmp(argv[0], "set", 3))
{
/*
* Set Password
*/
if ((argc >= 3) &&
(! strcmp("password", argv[1])))
{
char * password = NULL;
unsigned char user_id = (unsigned char)strtol(argv[2],
NULL,
0);
if (! user_id)
{
printf("Error. Invalid user ID: %d\n", user_id);
return -1;
}
if (argc == 3)
{
/* We need to prompt for a password */
char * tmp;
const char * password_prompt =
ipmi_user_build_password_prompt(user_id);
#ifdef HAVE_GETPASSPHRASE
if ((tmp = getpassphrase (password_prompt)))
#else
if ((tmp = (char*)getpass (password_prompt)))
#endif
{
password = strdup(tmp);
#ifdef HAVE_GETPASSPHRASE
if ((tmp = getpassphrase (password_prompt)))
#else
if ((tmp = (char*)getpass (password_prompt)))
#endif
{
if (strcmp(password, tmp))
{
printf("Error. Passwords to not match.\n");
return -1;
}
}
}
}
else
password = argv[3];
if (strlen(password) > 20)
{
printf("Error. Password is too long (> 20 bytes).\n");
return -1;
}
retval = ipmi_user_set_password(intf,
user_id,
IPMI_PASSWORD_SET_PASSWORD,
password,
strlen(password) > 16);
}
/*
* Set Name
*/
else if ((argc >= 2) &&
(! strcmp("name", argv[1])))
{
if (argc != 4)
{
print_user_usage();
return -1;
}
retval = ipmi_user_set_username(intf,
(unsigned char)strtol(argv[2],
NULL,
0),
argv[3]);
}
else
{
print_user_usage();
return -1;
}
}
/*
* Disable / Enable
*/
else if ((!strncmp(argv[0], "disable", 7)) ||
(!strncmp(argv[0], "enable", 6)))
{
unsigned char user_id;
unsigned char operation;
char null_password[16]; /* Not used, but required */
memset(null_password, 0, sizeof(null_password));
if (argc != 2)
{
print_user_usage();
return -1;
}
user_id = (unsigned char)strtol(argv[1],
NULL,
0);
if (! user_id)
{
printf("Error. Invalid user ID: %d\n", user_id);
return -1;
}
operation = (!strncmp(argv[0], "disable", 7))?
IPMI_PASSWORD_DISABLE_USER: IPMI_PASSWORD_ENABLE_USER;
retval = ipmi_user_set_password(intf,
user_id,
operation,
null_password,
0); /* This field is ignored */
}
else
{
print_user_usage();
retval = -1;
}
return retval;
}

154
ipmitool/lib/log.c Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <ipmitool/log.h>
struct logpriv_s {
char * name;
int daemon;
int level;
};
struct logpriv_s *logpriv;
static void log_reinit(void)
{
log_init(NULL, 0, 0);
}
void lprintf(int level, const char * format, ...)
{
static char logmsg[LOG_MSG_LENGTH];
va_list vptr;
if (!logpriv)
log_reinit();
if (logpriv->level < level)
return;
va_start(vptr, format);
vsnprintf(logmsg, LOG_MSG_LENGTH, format, vptr);
va_end(vptr);
if (logpriv->daemon)
syslog(level, "%s", logmsg);
else
printf("%s\n", logmsg);
return;
}
void lperror(int level, const char * format, ...)
{
static char logmsg[LOG_MSG_LENGTH];
va_list vptr;
if (!logpriv)
log_reinit();
if (logpriv->level < level)
return;
va_start(vptr, format);
vsnprintf(logmsg, LOG_MSG_LENGTH, format, vptr);
va_end(vptr);
if (logpriv->daemon)
syslog(level, "%s: %s", logmsg, strerror(errno));
else
fprintf(stderr, "%s: %s\n", logmsg, strerror(errno));
return;
}
/*
* open connection to syslog if daemon
*/
void log_init(const char * name, int isdaemon, int verbose)
{
if (logpriv)
return;
logpriv = malloc(sizeof(*logpriv));
if (!logpriv)
return;
if (name != NULL)
logpriv->name = strdup(name);
else
logpriv->name = strdup(LOG_NAME_DEFAULT);
logpriv->daemon = isdaemon;
logpriv->level = verbose + LOG_NOTICE;
if (logpriv->daemon)
openlog(logpriv->name, LOG_CONS, LOG_LOCAL4);
}
/*
* stop syslog logging if daemon mode,
* free used memory that stored log service
*/
void log_halt(void)
{
if (!logpriv)
return;
if (logpriv->name)
free(logpriv->name);
if (logpriv->daemon)
closelog();
free(logpriv);
}
int log_level_get(void)
{
return logpriv->level;
}
void log_level_set(int level)
{
logpriv->level = level;
}

View File

@ -37,18 +37,15 @@ SUBDIRS = plugins
MAINTAINERCLEANFILES = Makefile.in
ipmitool_SOURCES = ipmitool.c ipmishell.c
ipmitool_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
if IPMIEVD
EXTRA_DIST = bmcautoconf.sh
bin_PROGRAMS = ipmievd ipmitool
ipmievd_SOURCES = ipmievd.c
ipmievd_LDADD = $(top_srcdir)/lib/libipmitool.la $(top_srcdir)/src/plugins/libintf.la
else
EXTRA_DIST = bmcautoconf.sh ipmievd.c
bin_PROGRAMS = ipmitool
ipmievd_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
endif
ipmitool_SOURCES = ipmitool.c
ipmitool_LDADD = $(top_srcdir)/lib/libipmitool.la $(top_srcdir)/src/plugins/libintf.la
bin_SCRIPTS = bmcautoconf.sh
EXTRA_DIST = ipmievd.c
bin_PROGRAMS = ipmitool @IPMIEVD_BIN@
EXTRA_PROGRAMS = ipmitool ipmievd

View File

@ -1,152 +0,0 @@
#!/bin/bash
#
# bmcautoconf [interface] [channel]
#
#
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
DEBUG=0
# if the wrong channel is used serious problems could occur
# Channel 6 == eth0, top interface on v60x and v65x
# Channel 6 == eth1, top interface on LX50
# Channel 7 == eth1, bottom interface on v60x and v65x
# Channel 7 == eth0, bottom interface on LX50
CHANNEL=6
IFACE=eth0
# ipmitool interface
# open = OpenIPMI kernel driver
# [ipmi_msghandler, ipmi_kcs_drv, ipmi_devintf]
# imb = Intel IMB
IPMIINTF=open
# util locations
IPMITOOL=/usr/bin/ipmitool
PING=/bin/ping
ARP=/sbin/arp
IFCONFIG=/sbin/ifconfig
ROUTE=/sbin/route
ipmitool_lan_set ()
{
[ $# -lt 1 ] && return
PARAM=$1
VALUE=
[ $# -ge 2 ] && VALUE=$2
if [ $DEBUG -gt 0 ]; then
echo "Setting LAN parameter ${PARAM} to ${VALUE}"
echo "$IPMITOOL -I $IPMIINTF lan set $CHANNEL $PARAM $VALUE"
fi
$IPMITOOL -I $IPMIINTF lan set $CHANNEL $PARAM $VALUE
}
if [ ! -x $IPMITOOL ]; then
echo "Error: unable to find $IPMITOOL"
exit 1
fi
if [ $# -ge 1 ]; then
IFACE=$1
if ! $IFCONFIG $IFACE | grep -q "inet addr:" >/dev/null 2>&1 ; then
echo "Error: unable to find interface $IFACE"
exit 1
fi
fi
if [ $# -ge 2 ]; then
CHANNEL=$2
if [ $CHANNEL -ne 6 ] && [ $CHANNEL -ne 7 ]; then
echo "Invalid channel: $CHANNEL"
exit 1
fi
fi
[ $DEBUG -gt 0 ] && echo "Auto-configuring $IFACE (channel $CHANNEL)"
# IP Address
IP_ADDRESS=$( $IFCONFIG $IFACE | grep "inet addr:" | awk -F"[:[:space:]]+" '{ print $4 }' )
if [ X$IP_ADDRESS = X ]; then
echo "Unable to determine IP address for interface $IFACE"
exit 2
fi
# Netmask
IP_NETMASK=$( $IFCONFIG $IFACE | grep "inet addr:" | awk -F"[:[:space:]]+" '{ print $8 }' )
if [ X$IP_NETMASK = X ]; then
echo "Unable to determine IP netmask for interface $IFACE"
exit 3
fi
# MAC Address
MAC_ADDRESS=$( $IFCONFIG $IFACE | grep "HWaddr" | awk '{ print $5 }' )
if [ X$MAC_ADDRESS = X ]; then
echo "Unable to determine MAC address for interface $IFACE"
exit 4
fi
# default route IP Address
DEF_ROUTE_IP=$( $ROUTE -n | awk '/^0.0.0.0/ { print $2 }' )
if [ X$DEF_ROUTE_IP = X ]; then
echo "Unable to determine default route IP address"
exit 5
fi
# Default Route MAC Address
# (ping it first to populate arp table)
$PING -q -c1 $DEF_ROUTE_IP >/dev/null 2>&1
DEF_ROUTE_MAC=$( $ARP -an -i $IFACE | grep "$DEF_ROUTE_IP[^0-9]" | awk '{ print $4 }' )
if [ X$DEF_ROUTE_MAC = X ]; then
echo "Unable to determine default route MAC address"
exit 6
fi
ipmitool_lan_set "ipsrc" "static"
ipmitool_lan_set "ipaddr" $IP_ADDRESS
ipmitool_lan_set "netmask" $IP_NETMASK
ipmitool_lan_set "macaddr" $MAC_ADDRESS
ipmitool_lan_set "defgw ipaddr" $DEF_ROUTE_IP
ipmitool_lan_set "defgw macaddr" $DEF_ROUTE_MAC
ipmitool_lan_set "auth callback,user,operator,admin" "md2,md5"
ipmitool_lan_set "access" "on"
ipmitool_lan_set "user"
ipmitool_lan_set "arp generate" "on"
ipmitool_lan_set "arp interval" "8"
exit 0

View File

@ -40,15 +40,22 @@
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <linux/ipmi.h>
#include <config.h>
#ifdef HAVE_OPENIPMI_H
# include <linux/ipmi.h>
#else
# include "plugins/open/open.h"
#endif
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sel.h>
@ -57,12 +64,73 @@ extern int errno;
int verbose = 0;
int csv_output = 0;
static void daemonize(void)
{
pid_t pid;
int fd;
#ifdef SIGHUP
sigset_t sighup;
#endif
/* if we are started from init no need to become daemon */
if (getppid() == 1)
return;
#ifdef SIGHUP
sigemptyset(&sighup);
sigaddset(&sighup, SIGHUP);
if (sigprocmask(SIG_UNBLOCK, &sighup, nil) < 0)
fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
SIG_IGNORE(SIGHUP);
#endif
#ifdef SIGTTOU
SIG_IGNORE(SIGTTOU);
#endif
#ifdef SIGTTIN
SIG_IGNORE(SIGTTIN);
#endif
#ifdef SIGQUIT
SIG_IGNORE(SIGQUIT);
#endif
#ifdef SIGTSTP
SIG_IGNORE(SIGTSTP);
#endif
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#if defined(SIGTSTP) && defined(TIOCNOTTY)
if (setpgid(0, getpid()) == -1)
exit(1);
if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
#else
if (setpgrp() == -1)
exit(1);
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#endif
chdir("/");
umask(0);
for (fd=0; fd<64; fd++)
close(fd);
open("/dev/null", O_RDWR);
dup(0);
dup(0);
}
static int enable_event_msg_buffer(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char bmc_global_enables;
int r;
/* we must read/modify/write bmc global enables */
memset(&req, 0, sizeof(req));
@ -71,7 +139,7 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("ERROR:%x Get BMC Global Enables command\n",
lprintf(LOG_WARNING, "Get BMC Global Enables command filed [ccode %02x]",
rsp ? rsp->ccode : 0);
return -1;
}
@ -83,17 +151,38 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("ERROR:%x Set BMC Global Enables command\n",
lprintf(LOG_WARNING, "Set BMC Global Enables command failed [ccode %02x]",
rsp ? rsp->ccode : 0);
return -1;
}
if (verbose)
printf("BMC Event Message Buffer enabled.\n");
lprintf(LOG_DEBUG, "BMC Event Message Buffer enabled");
return 0;
}
static void log_event(struct sel_event_record * evt)
{
char *desc;
if (!evt)
return;
if (evt->record_type == 0xf0)
lprintf(LOG_ALERT, "Linux kernel panic: %.11s", (char *) evt + 5);
else if (evt->record_type >= 0xc0)
lprintf(LOG_NOTICE, "IPMI Event OEM Record %02x", evt->record_type);
else {
ipmi_get_event_desc(evt, &desc);
if (desc) {
lprintf(LOG_NOTICE, "%s Sensor %02x - %s",
ipmi_sel_get_sensor_type(evt->sensor_type),
evt->sensor_num, desc);
free(desc);
}
}
}
static void read_event(struct ipmi_intf * intf)
{
struct ipmi_addr addr;
@ -108,125 +197,121 @@ static void read_event(struct ipmi_intf * intf)
rv = ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
if (rv < 0) {
if (errno == EINTR)
/* abort */
return;
if (errno == EMSGSIZE) {
/* message truncated */
recv.msg.data_len = sizeof(data);
} else {
printf("ERROR: receiving IPMI message: %s\n",
strerror(errno));
switch (errno) {
case EINTR:
return; /* abort */
case EMSGSIZE:
recv.msg.data_len = sizeof(data); /* truncated */
break;
default:
lperror(LOG_ERR, "Unable to receive IPMI message");
return;
}
}
if (!recv.msg.data || recv.msg.data_len == 0) {
printf("ERROR: No data in event!\n");
lprintf(LOG_ERR, "No data in event");
return;
}
if (verbose > 1) {
printf(" type = %d\n", recv.recv_type);
printf(" channel = 0x%x\n", addr.channel);
printf(" msgid = %ld\n", recv.msgid);
printf(" netfn = 0x%x\n", recv.msg.netfn);
printf(" cmd = 0x%x\n", recv.msg.cmd);
printf(" data_len = %d\n", recv.msg.data_len);
printbuf(recv.msg.data, recv.msg.data_len, "data");
}
if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
printf("ERROR: Not an event!\n");
lprintf(LOG_ERR, "Type %x is not an event", recv.recv_type);
return;
}
if (verbose)
ipmi_sel_print_std_entry_verbose((struct sel_event_record *)recv.msg.data);
else
ipmi_sel_print_std_entry((struct sel_event_record *)recv.msg.data);
lprintf(LOG_DEBUG, "netfn:%x cmd:%x ccode:%d",
recv.msg.netfn, recv.msg.cmd, recv.msg.data[0]);
log_event((struct sel_event_record *)recv.msg.data);
}
static int do_exit(struct ipmi_intf * intf, int rv)
{
if (intf)
intf->close(intf);
ipmi_intf_exit();
log_halt();
exit(rv);
}
static void usage(void)
{
printf("usage: ipmievd [-hv]\n");
printf("\n");
printf(" -h This help\n");
printf(" -v Verbose (can use multiple times)\n");
printf("\n");
fprintf(stderr, "usage: ipmievd [-hvd]\n");
fprintf(stderr, "\n");
fprintf(stderr, " -h This help\n");
fprintf(stderr, " -v Verbose (can use multiple times)\n");
fprintf(stderr, " -s Do NOT daemonize\n");
fprintf(stderr, "\n");
}
int main(int argc, char ** argv)
{
struct ipmi_intf * intf;
int r, i=1, a;
int r, a;
int i = 1;
int daemon = 1;
struct pollfd pfd;
while ((a = getopt(argc, (char **)argv, "hv")) != -1) {
/* make sure we have UID 0 */
if (geteuid() || getuid()) {
fprintf(stderr, "Inadequate privledges\n");
do_exit(NULL, EXIT_FAILURE);
}
while ((a = getopt(argc, (char **)argv, "hvs")) != -1) {
switch (a) {
case 'h':
usage();
do_exit(NULL, EXIT_SUCCESS);
break;
case 'v':
verbose++;
break;
case 's':
daemon = 0;
break;
default:
usage();
do_exit(NULL, EXIT_FAILURE);
}
}
if (verbose)
printf("Loading OpenIPMI interface plugin.\n");
if (daemon)
daemonize();
/* init interface plugin support */
r = ipmi_intf_init();
if (r < 0) {
printf("ERROR: Unable to initialize plugin interface\n");
exit(EXIT_FAILURE);
}
log_init("ipmievd", daemon, verbose);
/* load interface plugin */
intf = ipmi_intf_load("intf_open");
/* load interface */
lprintf(LOG_DEBUG, "Loading OpenIPMI interface");
intf = ipmi_intf_load("open");
if (!intf) {
printf("ERROR: unable to load OpenIPMI interface plugin\n");
exit(EXIT_FAILURE);
lprintf(LOG_ERR, "Unable to load OpenIPMI interface");
do_exit(NULL, EXIT_FAILURE);
}
if (verbose)
printf("Connecting to OpenIPMI device.\n");
/* open connection to openipmi device */
r = intf->open(intf, NULL, 0, NULL, NULL);
lprintf(LOG_DEBUG, "Connecting to OpenIPMI device");
r = intf->open(intf);
if (r < 0) {
printf("ERROR: Unable to open OpenIPMI device\n");
exit(EXIT_FAILURE);
lprintf(LOG_ERR, "Unable to open OpenIPMI device");
do_exit(NULL, EXIT_FAILURE);
}
/* enable event message buffer */
lprintf(LOG_DEBUG, "Enabling event message buffer");
r = enable_event_msg_buffer(intf);
if (r < 0) {
printf("ERROR: Unable to enable event message buffer.\n");
lprintf(LOG_ERR, "Could not enable event message buffer");
do_exit(intf, EXIT_FAILURE);
}
if (verbose)
printf("Enabling event receiver.\n");
/* enable OpenIPMI event receiver */
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) {
perror("ERROR: Could not enable event receiver");
lprintf(LOG_DEBUG, "Enabling event receiver");
r = ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i);
if (r != 0) {
lperror(LOG_ERR, "Could not enable event receiver");
do_exit(intf, EXIT_FAILURE);
}
printf("ipmievd loaded, waiting for events...\n");
lprintf(LOG_NOTICE, "Waiting for events...");
for (;;) {
pfd.fd = intf->fd; /* wait on openipmi device */
@ -238,7 +323,7 @@ int main(int argc, char ** argv)
/* timeout is disabled */
break;
case -1:
perror("ERROR: poll operation failed");
lperror(LOG_CRIT, "Unable to read from IPMI device");
do_exit(intf, EXIT_FAILURE);
break;
default:
@ -247,8 +332,6 @@ int main(int argc, char ** argv)
}
}
if (verbose)
printf("Exiting.\n");
lprintf(LOG_DEBUG, "Shutting down...");
do_exit(intf, EXIT_SUCCESS);
}

312
ipmitool/src/ipmishell.c Normal file
View File

@ -0,0 +1,312 @@
/*
* Copyright (c) 2003, 2004 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_session.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define EXEC_BUF_SIZE 1024
#define EXEC_ARG_SIZE 32
extern void ipmi_cmd_print(void);
extern int ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv);
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_session_vals[];
#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#define RL_PROMPT "ipmitool> "
#define RL_TIMEOUT 30
static struct ipmi_intf * shell_intf;
/* This function attempts to keep lan sessions active
* so they do not time out waiting for user input. The
* readline timeout is set to 1 second but lan session
* timeout is ~60 seconds.
*/
static int rl_event_keepalive(void)
{
static int internal_timer = 0;
if (!shell_intf)
return -1;
if (!shell_intf->keepalive)
return 0;
if (internal_timer++ < RL_TIMEOUT)
return 0;
internal_timer = 0;
shell_intf->keepalive(shell_intf);
return 0;
}
int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
{
char *pbuf, **ap, *__argv[20];
int __argc, rc=0;
rl_readline_name = "ipmitool";
/* this essentially disables command completion
* until its implemented right, otherwise we get
* the current directory contents... */
rl_bind_key('\t', rl_insert);
if (intf->keepalive) {
/* hook to keep lan sessions active */
shell_intf = intf;
rl_event_hook = rl_event_keepalive;
/* set to 1 second */
rl_set_keyboard_input_timeout(1000*1000);
}
while ((pbuf = (char *)readline(RL_PROMPT)) != NULL) {
if (strlen(pbuf) == 0) {
free(pbuf);
continue;
}
if (!strncmp(pbuf, "quit", 4) || !strncmp(pbuf, "exit", 4)) {
free(pbuf);
return 0;
}
if (!strncmp(pbuf, "help", 4) || !strncmp(pbuf, "?", 1)) {
ipmi_cmd_print();
free(pbuf);
continue;
}
/* for the all-important up arrow :) */
add_history(pbuf);
__argc = 0;
ap = __argv;
for (*ap = strtok(pbuf, " \t"); *ap != NULL; *ap = strtok(NULL, " \t")) {
__argc++;
if (**ap != '\0') {
if (++ap >= &__argv[20])
break;
}
}
if (__argc && __argv[0])
rc = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1]));
free(pbuf);
}
return rc;
}
#else /* HAVE_READLINE */
int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
{
printf("Compiled without readline support, shell is disabled.\n");
return -1;
}
#endif /* HAVE_READLINE */
static void ipmi_set_usage(void)
{
printf("Usage: set <option> <value>\n\n");
printf("Options are:\n");
printf(" hostname <host> Session hostname\n");
printf(" username <user> Session username\n");
printf(" password <pass> Session password\n");
printf(" privlvl <level> Session privilege level force\n");
printf(" authtype <type> Authentication type force\n");
printf(" localaddr <addr> Local IPMB address\n");
printf(" targetaddr <addr> Remote target IPMB address\n");
printf(" port <port> Remote RMCP port\n");
printf(" csv [level] enable output in comma separated format\n");
printf(" verbose [level] Verbose level\n");
printf("\n");
}
int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
{
if (!argc || !strncmp(argv[0], "help", 4)) {
ipmi_set_usage();
return -1;
}
/* these options can have no arguments */
if (!strncmp(argv[0], "verbose", 7)) {
verbose = (argc > 1) ? atoi(argv[1]) : verbose+1;
return 0;
}
if (!strncmp(argv[0], "csv", 3)) {
csv_output = (argc > 1) ? atoi(argv[1]) : 1;
return 0;
}
/* the rest need an argument */
if (argc == 1) {
ipmi_set_usage();
return -1;
}
if (!strncmp(argv[0], "host", 4) || !strncmp(argv[0], "hostname", 8)) {
ipmi_intf_session_set_hostname(intf, argv[1]);
printf("Set session hostname to %s\n", intf->session->hostname);
}
else if (!strncmp(argv[0], "user", 4) || !strncmp(argv[0], "username", 8)) {
ipmi_intf_session_set_username(intf, argv[1]);
printf("Set session username to %s\n", intf->session->username);
}
else if (!strncmp(argv[0], "pass", 4) || !strncmp(argv[0], "password", 8)) {
ipmi_intf_session_set_password(intf, argv[1]);
printf("Set session password\n");
}
else if (!strncmp(argv[0], "authtype", 8)) {
unsigned char authtype;
authtype = (unsigned char)str2val(argv[1], ipmi_authtype_session_vals);
ipmi_intf_session_set_authtype(intf, authtype);
printf("Set session authtype to %s\n",
val2str(intf->session->authtype_set, ipmi_authtype_session_vals));
}
else if (!strncmp(argv[0], "privlvl", 7)) {
unsigned char privlvl;
privlvl = (unsigned char)str2val(argv[1], ipmi_privlvl_vals);
ipmi_intf_session_set_privlvl(intf, privlvl);
printf("Set session privilege level to %s\n",
val2str(intf->session->privlvl, ipmi_privlvl_vals));
}
else if (!strncmp(argv[0], "port", 4)) {
int port = atoi(argv[1]);
ipmi_intf_session_set_port(intf, port);
printf("Set session port to %d\n", intf->session->port);
}
else if (!strncmp(argv[0], "localaddr", 9)) {
intf->my_addr = (unsigned char)strtol(argv[1], NULL, 0);
printf("Set local IPMB address to 0x%02x\n", intf->my_addr);
}
else if (!strncmp(argv[0], "targetaddr", 10)) {
intf->target_addr = (unsigned char)strtol(argv[1], NULL, 0);
printf("Set remote IPMB address to 0x%02x\n", intf->target_addr);
}
else {
ipmi_set_usage();
return -1;
}
return 0;
}
int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv)
{
FILE * fp;
char buf[EXEC_BUF_SIZE];
char * ptr, * tok, * ret;
int __argc, i, r;
char * __argv[EXEC_ARG_SIZE];
int rc=0;
if (argc < 1) {
printf("Usage: exec <filename>\n");
return -1;
}
fp = ipmi_open_file_read(argv[0]);
if (!fp)
return -1;
while (!feof(fp)) {
ret = fgets(buf, EXEC_BUF_SIZE, fp);
if (!ret)
continue;
/* clip off optional comment tail indicated by # */
ptr = strchr(buf, '#');
if (ptr)
*ptr = '\0';
else
ptr = buf + strlen(buf);
/* clip off trailing and leading whitespace */
ptr--;
while (isspace(*ptr) && ptr >= buf)
*ptr-- = '\0';
ptr = buf;
while (isspace(*ptr))
ptr++;
if (!strlen(ptr))
continue;
/* parse it and make argument list */
__argc = 0;
tok = strtok(ptr, " ");
while (tok) {
if (__argc < EXEC_ARG_SIZE)
__argv[__argc++] = strdup(tok);
tok = strtok(NULL, " ");
}
/* now run the command, save the result if not successful */
r = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1]));
if (r != 0)
rc = r;
/* free argument list */
for (i=0; i<__argc; i++) {
if (__argv[i] != NULL) {
free(__argv[i]);
__argv[i] = NULL;
}
}
}
fclose(fp);
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2003, 2004 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -35,33 +35,111 @@
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <config.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_session.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_fru.h>
#include <ipmitool/ipmi_isol.h>
#include <ipmitool/ipmi_sol.h>
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_chassis.h>
#include <ipmitool/ipmi_bmc.h>
#include <ipmitool/ipmi_sensor.h>
#include <ipmitool/ipmi_channel.h>
#include <ipmitool/ipmi_session.h>
#include <ipmitool/ipmi_event.h>
#include <ipmitool/ipmi_user.h>
#include <ipmitool/ipmi_raw.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define OPTION_STRING "I:hVvcgEaH:P:f:U:p:L:A:t:m:"
struct ipmi_session lan_session;
int csv_output = 0;
int verbose = 0;
void usage(void)
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_session_vals[];
/* defined in ipmishell.c */
extern int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv);
extern int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv);
extern int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv);
struct ipmi_cmd {
int (*func)(struct ipmi_intf * intf, int argc, char ** argv);
char * name;
char * desc;
} ipmi_cmd_list[] = {
{ ipmi_raw_main, "raw", "Send a RAW IPMI request and print response" },
{ ipmi_lanp_main, "lan", "Configure LAN Channels" },
{ ipmi_chassis_main, "chassis", "Get chassis status and set power state" },
{ ipmi_event_main, "event", "Send pre-defined events to BMC" },
{ ipmi_bmc_main, "bmc", "Print BMC status and configure global enables" },
{ ipmi_sdr_main, "sdr", "Print Sensor Data Repository entries and readings" },
{ ipmi_sensor_main, "sensor", "Print detailed sensor information" },
{ ipmi_fru_main, "fru", "Print built-in FRU and scan SDR for FRU locators" },
{ ipmi_sel_main, "sel", "Print System Evelnt Log" },
{ ipmi_sol_main, "sol", "Configure IPMIv2.0 Serial-over-LAN" },
{ ipmi_isol_main, "isol", "Configure Intel IPMIv1.5 Serial-over-LAN" },
{ ipmi_user_main, "user", "Configure BMC users" },
{ ipmi_channel_main, "channel", "Configure BMC channels" },
{ ipmi_session_main, "session", "Print session information" },
{ ipmi_shell_main, "shell", "Launch interactive IPMI shell" },
{ ipmi_exec_main, "exec", "Run list of commands from file" },
{ ipmi_set_main, "set", "Set runtime variable for shell and exec" },
{ NULL },
};
/*
* Print all the commands in the above table to stdout
* used for help text on command line and shell
*/
void ipmi_cmd_print(void)
{
struct ipmi_cmd * cmd;
printf("Commands:\n");
for (cmd=ipmi_cmd_list; cmd->func; cmd++) {
if (!cmd->desc)
continue;
printf("\t%-12s %s\n", cmd->name, cmd->desc);
}
printf("\n");
}
/*
* Run a command from ipmi_cmd_list based on parameters.
*/
int ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv)
{
struct ipmi_cmd * cmd;
for (cmd=ipmi_cmd_list; cmd->func; cmd++) {
if (!strncmp(name, cmd->name, strlen(cmd->name)))
break;
}
if (!cmd->func) {
printf("Invalid command: %s\n", name);
return -1;
}
return cmd->func(intf, argc, argv);
}
static void ipmitool_usage(void)
{
printf("ipmitool version %s\n", VERSION);
printf("\n");
@ -70,208 +148,94 @@ void usage(void)
printf(" -h This help\n");
printf(" -V Show version information\n");
printf(" -v Verbose (can use multiple times)\n");
printf(" -c CSV output suitable for parsing\n");
printf(" -g Attempt to be extra robust in LAN communications\n");
printf(" -c Display output in comma separated format\n");
printf(" -I intf Interface to use\n");
printf(" -H hostname Remote host name for LAN interface\n");
printf(" -p port Remote RMCP port (default is 623)\n");
printf(" -P password Remote administrator password\n");
printf(" -I intf Inteface to use\n");
printf("\n\n");
exit(EXIT_SUCCESS);
}
int ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char netfn, cmd;
int i;
unsigned char data[32];
if (argc < 2 || !strncmp(argv[0], "help", 4)) {
printf("RAW Commands: raw <netfn> <cmd> [data]\n");
return -1;
}
netfn = (unsigned char)strtol(argv[0], NULL, 0);
cmd = (unsigned char)strtol(argv[1], NULL, 0);
memset(data, 0, sizeof(data));
memset(&req, 0, sizeof(req));
req.msg.netfn = netfn;
req.msg.cmd = cmd;
req.msg.data = data;
for (i=2; i<argc; i++) {
unsigned char val = (unsigned char)strtol(argv[i], NULL, 0);
req.msg.data[i-2] = val;
req.msg.data_len++;
}
if (req.msg.data_len) {
for (i=0; i<req.msg.data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", req.msg.data[i]);
}
printf("\n");
}
printf("RAW REQ (netfn=0x%x cmd=0x%x data_len=%d)\n",
req.msg.netfn, req.msg.cmd, req.msg.data_len);
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x sending RAW command\n",
rsp ? rsp->ccode : 0);
return -1;
}
printf("RAW RSP (%d bytes)\n", rsp->data_len);
for (i=0; i<rsp->data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", rsp->data[i]);
}
printf(" -p port Remote RMCP port [default=623]\n");
printf(" -L level Remote session privilege level [default=USER]\n");
printf(" -A authtype Force use of authentication type NONE, PASSWORD, MD2 or MD5\n");
printf(" -U username Remote session username\n");
printf(" -P password Remote session password\n");
printf(" -f file Read remote session password from file\n");
printf(" -a Prompt for remote password\n");
printf(" -E Read password from IPMI_PASSWORD environment variable\n");
printf(" -m address Set local IPMB address\n");
printf(" -t address Bridge request to remote target address\n");
printf("\n");
return 0;
ipmi_intf_print();
ipmi_cmd_print();
}
static int
ipmi_get_user_access(struct ipmi_intf * intf, unsigned char channel, unsigned char userid)
static char * ipmi_password_file_read(char * filename)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[2];
FILE * fp;
char * pass = NULL;
int l;
memset(&req, 0, sizeof(req));
rqdata[0] = channel & 0xf;
rqdata[1] = userid & 0x3f;
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x44;
req.msg.data = rqdata;
req.msg.data_len = 2;
pass = malloc(16);
if (!pass)
return NULL;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Get User Access Command (0x%x)\n",
rsp ? rsp->ccode : 0, channel);
return -1;
fp = ipmi_open_file_read((const char *)filename);
if (!fp)
return NULL;
/* read in id */
if (fgets(pass, 16, fp) == NULL) {
fclose(fp);
return NULL;
}
printf("Maximum User IDs : %d\n", rsp->data[0] & 0x3f);
printf("Enabled User IDs : %d\n", rsp->data[1] & 0x3f);
printf("Fixed Name User IDs : %d\n", rsp->data[2] & 0x3f);
printf("Access Available : %s\n", (rsp->data[3] & 0x40) ? "callback" : "call-in / callback");
printf("Link Authentication : %sabled\n", (rsp->data[3] & 0x20) ? "en" : "dis");
printf("IPMI Messaging : %sabled\n", (rsp->data[3] & 0x10) ? "en" : "dis");
// printf("Privilege Level : %s\n", val2str(rsp->data[3] & 0x0f, ipmi_privlvl_vals));
/* remove trailing whitespace */
l = strcspn(pass, " \r\n\t");
if (l > 0)
pass[l] = '\0';
return 0;
fclose(fp);
return pass;
}
static int
ipmi_send_platform_event(struct ipmi_intf * intf, int num)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char rqdata[8];
memset(&req, 0, sizeof(req));
memset(rqdata, 0, 8);
printf("Sending ");
/* IPMB/LAN/etc */
switch (num) {
case 0: /* temperature */
printf("Temperature");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x01; /* Sensor Type */
rqdata[2] = 0x30; /* Sensor # */
rqdata[3] = 0x04; /* Event Dir / Event Type */
rqdata[4] = 0x00; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
case 1: /* correctable ECC */
printf("Memory Correctable ECC");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x0c; /* Sensor Type */
rqdata[2] = 0x01; /* Sensor # */
rqdata[3] = 0x6f; /* Event Dir / Event Type */
rqdata[4] = 0x00; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
case 2: /* uncorrectable ECC */
printf("Memory Uncorrectable ECC");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x0c; /* Sensor Type */
rqdata[2] = 0x01; /* Sensor # */
rqdata[3] = 0x6f; /* Event Dir / Event Type */
rqdata[4] = 0x01; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
case 3: /* parity error */
printf("Memory Parity Error");
rqdata[0] = 0x04; /* EvMRev */
rqdata[1] = 0x0c; /* Sensor Type */
rqdata[2] = 0x01; /* Sensor # */
rqdata[3] = 0x6f; /* Event Dir / Event Type */
rqdata[4] = 0x02; /* Event Data 1 */
rqdata[5] = 0x00; /* Event Data 2 */
rqdata[6] = 0x00; /* Event Data 3 */
break;
default:
printf("Invalid event number: %d\n", num);
return -1;
}
printf(" event to BMC\n");
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = 0x02;
req.msg.data = rqdata;
req.msg.data_len = 7;
rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) {
printf("Error:%x Platform Event Message Command\n", rsp?rsp->ccode:0);
return -1;
}
return 0;
}
int main(int argc, char ** argv)
{
int (*submain)(struct ipmi_intf *, int, char **);
struct ipmi_intf * intf = NULL;
char * hostname = NULL, * password = NULL, * username = NULL;
int argflag, i, rc=0, port = 623, pedantic = 0;
char intfname[32];
unsigned char privlvl = 0;
unsigned char target_addr = 0;
unsigned char my_addr = 0;
unsigned char authtype = 0;
char * tmp = NULL;
char * hostname = NULL;
char * username = NULL;
char * password = NULL;
char * intfname = NULL;
char * progname = NULL;
int port = 0;
int argflag, i;
int rc = 0;
int thump = 0;
if (ipmi_intf_init() < 0)
exit(EXIT_FAILURE);
/* save program name */
if (!(progname = strrchr(argv[0], '/')))
progname = argv[0];
else
progname++;
while ((argflag = getopt(argc, (char **)argv, "hVvcgI:H:P:U:p:")) != -1)
while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1)
{
switch (argflag) {
case 'I':
intfname = strdup(optarg);
break;
case 'h':
usage();
ipmitool_usage();
goto out_free;
break;
case 'V':
printf("ipmitool version %s\n", VERSION);
exit(EXIT_SUCCESS);
printf("%s version %s\n", progname, VERSION);
goto out_free;
break;
case 'g':
pedantic = 1;
thump = 1;
break;
case 'v':
verbose++;
@ -279,141 +243,139 @@ int main(int argc, char ** argv)
case 'c':
csv_output = 1;
break;
case 'I':
memset(intfname, 0, sizeof(intfname));
i = snprintf(intfname, sizeof(intfname), "intf_%s", optarg);
intf = ipmi_intf_load(intfname);
if (!intf) {
printf("Error loading interface %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case 'H':
hostname = strdup(optarg);
break;
case 'P':
if (password)
free(password);
password = strdup(optarg);
/* Prevent password snooping with ps */
i = strlen (optarg);
memset (optarg, 'X', i);
break;
case 'f':
if (password)
free(password);
password = ipmi_password_file_read(optarg);
if (!password)
printf("Unable to read password from file %s.\n", optarg);
break;
case 'E':
if ((tmp = getenv ("IPMITOOL_PASSWORD")))
{
if (password)
free(password);
password = strdup(tmp);
}
else if ((tmp = getenv("IPMI_PASSWORD")))
{
if (password)
free(password);
password = strdup(tmp);
}
else printf("Unable to read password from environment.\n");
break;
case 'a':
#ifdef HAVE_GETPASSPHRASE
if ((tmp = getpassphrase ("Password: ")))
#else
if ((tmp = getpass ("Password: ")))
#endif
{
if (password)
free(password);
password = strdup(tmp);
}
break;
case 'U':
username = strdup(optarg);
break;
case 'L':
privlvl = (unsigned char)str2val(optarg, ipmi_privlvl_vals);
if (!privlvl)
printf("Invalid privilege level %s!\n", optarg);
break;
case 'A':
authtype = (int)str2val(optarg, ipmi_authtype_session_vals);
break;
case 'p':
port = atoi(optarg);
break;
case 't':
target_addr = (unsigned char)strtol(optarg, NULL, 0);
break;
case 'm':
my_addr = (unsigned char)strtol(optarg, NULL, 0);
break;
default:
usage();
ipmitool_usage();
goto out_free;
}
}
/* check for command before doing anything */
if (argc-optind <= 0) {
printf("No command provided!\n");
usage();
ipmitool_usage();
goto out_free;
}
if (!intf) {
printf("No interface specified!\n");
usage();
}
intf->pedantic = pedantic;
if (!strncmp(argv[optind], "help", 4)) {
printf("Commands: bmc, chaninfo, chassis, event, fru, lan, raw, sdr, sel, sensor, sol, userinfo\n");
goto out_free;
}
else if (!strncmp(argv[optind], "event", 5)) {
if (argc-optind-1 > 0) {
unsigned char c = (unsigned char)strtol(argv[optind+1], NULL, 0);
if (intf->open(intf, hostname, port, username, password) < 0)
goto out_free;
ipmi_send_platform_event(intf, c);
goto out_close;
} else {
printf("event <num>\n");
goto out_free;
}
}
else if (!strncmp(argv[optind], "bmc", 3)) {
submain = ipmi_bmc_main;
}
else if (!strncmp(argv[optind], "chassis", 7)) {
submain = ipmi_chassis_main;
}
else if (!strncmp(argv[optind], "fru", 3)) {
submain = ipmi_fru_main;
}
else if (!strncmp(argv[optind], "lan", 3)) {
submain = ipmi_lanp_main;
}
else if (!strncmp(argv[optind], "sdr", 3)) {
submain = ipmi_sdr_main;
}
else if (!strncmp(argv[optind], "sel", 3)) {
submain = ipmi_sel_main;
}
else if (!strncmp(argv[optind], "sensor", 6)) {
submain = ipmi_sensor_main;
}
else if (!strncmp(argv[optind], "sol", 3)) {
submain = ipmi_sol_main;
}
else if (!strncmp(argv[optind], "raw", 3)) {
submain = ipmi_raw_main;
}
else if (!strncmp(argv[optind], "userinfo", 8)) {
if (argc-optind-1 > 0) {
unsigned char c = (unsigned char)strtol(argv[optind+1], NULL, 0);
rc = intf->open(intf, hostname, port, username, password);
if (rc < 0)
goto out_free;
ipmi_get_user_access(intf, c, 1);
goto out_close;
}
else {
printf("userinfo <channel>\n");
goto out_free;
}
}
else if (!strncmp(argv[optind], "chaninfo", 8)) {
if (argc-optind-1 > 0) {
unsigned char c = (unsigned char)strtol(argv[optind+1], NULL, 0);
rc = intf->open(intf, hostname, port, username, password);
if (rc < 0)
goto out_free;
verbose++;
ipmi_get_channel_info(intf, c);
verbose--;
goto out_close;
}
else {
printf("chaninfo <channel>\n");
goto out_free;
}
}
else {
printf("Invalid comand: %s\n", argv[optind]);
rc = -1;
ipmitool_usage();
goto out_free;
}
if (!submain)
/* load interface */
intf = ipmi_intf_load(intfname);
if (!intf) {
printf("Error loading interface %s\n", intfname);
goto out_free;
}
intf->thump = thump;
if (intf->open) {
rc = intf->open(intf, hostname, port, username, password);
if (rc < 0)
goto out_free;
/* setup log */
log_init(progname, 0, verbose);
/* set session variables */
if (hostname)
ipmi_intf_session_set_hostname(intf, hostname);
if (username)
ipmi_intf_session_set_username(intf, username);
if (password)
ipmi_intf_session_set_password(intf, password);
if (port)
ipmi_intf_session_set_port(intf, port);
if (authtype)
ipmi_intf_session_set_authtype(intf, authtype);
if (privlvl)
ipmi_intf_session_set_privlvl(intf, privlvl);
else
ipmi_intf_session_set_privlvl(intf,
IPMI_SESSION_PRIV_ADMIN); /* default */
/* setup IPMB local and target address if given */
intf->my_addr = my_addr ? : IPMI_BMC_SLAVE_ADDR;
if (target_addr) {
/* need to open the interface first */
if (intf->open)
intf->open(intf);
intf->target_addr = target_addr;
/* must be admin level to do this over lan */
ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN);
}
rc = submain(intf, argc-optind-1, &(argv[optind+1]));
/* now we finally run the command */
ipmi_cmd_run(intf, argv[optind], argc-optind-1, &(argv[optind+1]));
out_close:
if (intf->close)
if (intf->opened && intf->close)
intf->close(intf);
ipmi_intf_exit();
out_free:
log_halt();
if (intfname)
free(intfname);
if (hostname)
free(hostname);
if (username)

View File

@ -32,18 +32,16 @@
# in the design, construction, operation or maintenance of any nuclear
# facility.
plugindir = $(pluginpath)
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include $(INCLTDL)
MAINTAINERCLEANFILES = Makefile.in ipmi_intf_static.c
EXTRA_DIST = ipmi_intf_static.c.in
INCLUDES = -I$(top_srcdir)/include
SUBDIRS = @INTF_LAN@ @INTF_OPEN@
DIST_SUBDIRS = lan open
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@
DIST_SUBDIRS = lan lanplus open lipmi imb
noinst_LTLIBRARIES = libintf.la
libintf_la_SOURCES = ipmi_intf.c ipmi_intf_static.c
libintf_la_SOURCES = ipmi_intf.c
libintf_la_LDFLAGS = -export-dynamic
libintf_la_LIBADD = $(LIBLTDL) @STATIC_INTF_LIB@
libintf_la_DEPENDENCIES = $(LIBLTDL) @STATIC_INTF_LIB@
libintf_la_LIBADD = @IPMITOOL_INTF_LIB@
libintf_la_DEPENDENCIES = @IPMITOOL_INTF_LIB@

View File

@ -0,0 +1,43 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_imb.la
noinst_LTLIBRARIES = @INTF_IMB_LIB@
libintf_imb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_imb_la_SOURCES = imbapi.c imbapi.h imb.c

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include "imbapi.h"
#define IPMI_IMB_TIMEOUT (1000 * 1000)
#define IPMI_IMB_MAX_RETRY 3
#define IPMI_IMB_DEV "/dev/imb"
#define IPMI_IMB_BUF_SIZE 64
extern int verbose;
static int ipmi_imb_open(struct ipmi_intf * intf)
{
struct stat stbuf;
if (stat(IPMI_IMB_DEV, &stbuf) < 0) {
printf("Error: no IMB driver found at %s!\n", IPMI_IMB_DEV);
return -1;
}
intf->opened = 1;
return 0;
}
static void ipmi_imb_close(struct ipmi_intf * intf)
{
intf->opened = 0;
}
static struct ipmi_rs * ipmi_imb_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
{
IMBPREQUESTDATA imbreq;
static struct ipmi_rs rsp;
int status, i;
unsigned char ccode;
imbreq.rsSa = IPMI_BMC_SLAVE_ADDR;
imbreq.rsLun = 0;
imbreq.busType = 0;
imbreq.netFn = req->msg.netfn;
imbreq.cmdType = req->msg.cmd;
imbreq.data = req->msg.data;
imbreq.dataLength = req->msg.data_len;
if (verbose > 1) {
printf("IMB rsSa : %x\n", imbreq.rsSa);
printf("IMB netFn : %x\n", imbreq.netFn);
printf("IMB cmdType : %x\n", imbreq.cmdType);
printf("IMB dataLength : %d\n", imbreq.dataLength);
}
rsp.data_len = IPMI_IMB_BUF_SIZE;
memset(rsp.data, 0, rsp.data_len);
for (i=0; i<IPMI_IMB_MAX_RETRY; i++) {
if (verbose > 2)
printbuf(imbreq.data, imbreq.dataLength, "ipmi_imb request");
status = SendTimedImbpRequest(&imbreq, IPMI_IMB_TIMEOUT,
rsp.data, &rsp.data_len, &ccode);
if (status == 0) {
if (verbose > 2)
printbuf(rsp.data, rsp.data_len, "ipmi_imb response");
break;
}
/* error */
printf("Error sending IMB request, status=%x ccode=%x\n",
status, ccode);
}
rsp.ccode = ccode;
return &rsp;
}
struct ipmi_intf ipmi_imb_intf = {
name: "imb",
desc: "Intel IMB Interface",
open: ipmi_imb_open,
close: ipmi_imb_close,
sendrecv: ipmi_imb_send_cmd,
target_addr: IPMI_BMC_SLAVE_ADDR,
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,652 @@
/*M*
// PVCS:
// $Workfile: imb_api.h $
// $Revision: 1.2 $
// $Modtime: Jul 22 2002 16:40:32 $
// $Author: iceblink $
//
// Combined include files needed for imbapi.c
//
*M*/
/*----------------------------------------------------------------------*
The BSD License
Copyright (c) 2002, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
a.. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
b.. 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.
c.. Neither the name of Intel Corporation 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 OWNER 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.
*----------------------------------------------------------------------*/
#ifndef _WINDEFS_H
#define _WINDEFS_H
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef WIN32
/* WIN32 defines this in stdio.h */
#ifndef _WCHAR_T
#define _WCHAR_T
typedef long wchar_t;
#endif
#endif
#define far
#define near
#define FAR far
#define NEAR near
#ifndef CONST
#define CONST const
#endif
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BOOL near *PBOOL;
typedef BOOL far *LPBOOL;
typedef BYTE near *PBYTE;
typedef BYTE far *LPBYTE;
typedef int near *PINT;
typedef int far *LPINT;
typedef WORD near *PWORD;
typedef WORD far *LPWORD;
typedef long far *LPLONG;
typedef DWORD near *PDWORD;
typedef DWORD far *LPDWORD;
typedef void far *LPVOID;
typedef CONST void far *LPCVOID;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int *PUINT;
typedef DWORD NTSTATUS;
/*
File structures
*/
#ifndef WIN32
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
/* HANDLE hEvent; */
} OVERLAPPED, *LPOVERLAPPED;
#endif
/*
* Data structure redefines
*/
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef char * PCHAR;
typedef short * PSHORT;
typedef long * PLONG;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef unsigned char * PUCHAR;
typedef unsigned short * PUSHORT;
typedef unsigned long * PULONG;
typedef char CCHAR;
typedef short CSHORT;
typedef ULONG CLONG;
typedef CCHAR * PCCHAR;
typedef CSHORT * PCSHORT;
typedef CLONG * PCLONG;
typedef void * PVOID;
#ifndef WIN32
typedef void VOID;
typedef struct _LARGE_INTEGER {
ULONG LowPart;
LONG HighPart;
} LARGE_INTEGER;
typedef struct _ULARGE_INTEGER {
ULONG LowPart;
ULONG HighPart;
} ULARGE_INTEGER;
#endif
typedef LARGE_INTEGER * PLARGE_INTEGER;
typedef LARGE_INTEGER PHYSICAL_ADDRESS;
typedef LARGE_INTEGER * PPHYSICAL_ADDRESS;
typedef ULARGE_INTEGER * PULARGE_INTEGER;
typedef UCHAR BOOLEAN;
typedef BOOLEAN *PBOOLEAN;
typedef wchar_t WCHAR;
typedef WCHAR *PWCHAR, *PWSTR;
typedef CONST WCHAR *LPCWSTR, *PCWSTR;
#ifndef _SYS_TYPES_H
#ifndef _CADDR_T
#define _CADDR_T
typedef char * caddr_t;
#endif
#endif
/*
Unicode strings are counted 16-bit character strings. If they are
NULL terminated, Length does not include trailing NULL.
*/
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
#define UNICODE_NULL ((WCHAR)0) /* winnt*/
#define IN /* */
#define OUT /* */
#define OPTIONAL /* */
#ifndef WIN32
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
#define UNREFERENCED_PARAMETER(x)
typedef int HANDLE;
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
#endif
typedef HANDLE *PHANDLE;
/*
Define the method codes for how buffers are passed for I/O and FS controls
*/
#define METHOD_BUFFERED 0
/*
Define the access check value for any access
The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
constants *MUST* always be in sync.
*/
#define FILE_ANY_ACCESS 0
/*
These are the generic rights.
*/
#define MAX_PATH 260
#define GetLastError() (NTstatus.Status)
/*
Macro definition for defining IOCTL and FSCTL function control codes. Note
that function codes 0-2047 are reserved for Microsoft Corporation, and
2048-4095 are reserved for customers.
*/
/*
* Linux drivers expect ioctls defined using macros defined in ioctl.h.
* So, instead of using the CTL_CODE defined for NT and UW, I define CTL_CODE
* using these macros. That way imb_if.h, where the ioctls are defined get
* to use the correct ioctl command we expect.
* Notes: I am using the generic _IO macro instead of the more specific
* ones. The macros expect 8bit entities, so I am cleaning what is sent to
* us from imb_if.h - Mahendra
*/
#ifndef WIN32
#define CTL_CODE(DeviceType, Function, Method, Access)\
_IO(DeviceType & 0x00FF, Function & 0x00FF)
#else
#define CTL_CODE( DeviceType, Function, Method, Access ) ((ULONG)( \
((ULONG)(DeviceType) << 16) | ((ULONG)(Access) << 14) | ((ULONG)(Function) << 2) | ((ULONG)Method) \
))
#endif
#endif /*_WINDEFS_H */
/*----------------------------------------------------------------------*/
#ifndef _SMI_H
#define _SMI_H
#define SMI_Version1_00 0x00001000
struct smi {
DWORD smi_VersionNo;
DWORD smi_Reserved1;
DWORD smi_Reserved2;
LPVOID ntstatus; /* address of NT status block*/
LPVOID lpvInBuffer; /* address of buffer for input data*/
DWORD cbInBuffer; /* size of input buffer*/
LPVOID lpvOutBuffer; /* address of output buffer*/
DWORD cbOutBuffer; /* size of output buffer*/
LPDWORD lpcbBytesReturned; /* address of actual bytes of output*/
LPOVERLAPPED lpoOverlapped; /* address of overlapped structure*/
};
#ifndef STATUS_SUCCESS
typedef struct _IO_STATUS_BLOCK {
ULONG Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
/*
* I2C ioctl's return NTStatus codes
*/
#define STATUS_SUCCESS (0x00000000U)
#define STATUS_UNSUCCESSFUL (0xC0000001U)
#define STATUS_DEVICE_BUSY (0x80000011U)
#ifndef WIN32
#define STATUS_PENDING (0x00000103U)
// see <win2000ddk>\inc\winnt.h(1171)
#endif
#define STATUS_INVALID_PARAMETER (0xC000000DU)
#define STATUS_INVALID_DEVICE_REQUEST (0xC0000010U)
#define STATUS_BUFFER_TOO_SMALL (0xC0000023U)
#define STATUS_FILE_CLOSED (0xC0000128U)
#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AU)
#define STATUS_NO_DATA_DETECTED (0x80000022U)
#define STATUS_NO_SUCH_DEVICE (0xC000000EU)
#define STATUS_ALLOTTED_EXCEEDED (0xC000000FU)
#define STATUS_IO_DEVICE_ERROR (0xC0000185U)
#define STATUS_TOO_MANY_OPEN_FILES (0xC000011FU)
#define STATUS_ACCESS_DENIED (0xC0000022U)
#define STATUS_BUFFER_OVERFLOW (0x80000005U)
#define STATUS_CANCELLED (0xC0000120U)
#endif /* STATUS_SUCCESS*/
#endif /* _SMI_H*/
/*----------------------------------------------------------------------*/
#ifndef IMB_IF__
#define IMB_IF__
/*
* This is the structure passed in to the IOCTL_IMB_SHUTDOWN_CODE request
*/
typedef struct {
int code;
int delayTime;
} ShutdownCmdBuffer;
#define SD_NO_ACTION 0
#define SD_RESET 1
#define SD_POWER_OFF 2
#pragma pack(1)
/*
* This is the generic IMB packet format, the final checksum cant be
* represented in this structure and will show up as the last data byte
*/
typedef struct {
BYTE rsSa;
BYTE nfLn;
BYTE cSum1;
BYTE rqSa;
BYTE seqLn;
BYTE cmd;
BYTE data[1];
} ImbPacket;
#define MIN_IMB_PACKET_SIZE 7
#define MAX_IMB_PACKET_SIZE 33
/*
* This is the standard IMB response format where the first byte of
* IMB packet data is interpreted as a command completion code.
*/
typedef struct {
BYTE rsSa;
BYTE nfLn;
BYTE cSum1;
BYTE rqSa;
BYTE seqLn;
BYTE cmd;
BYTE cCode;
BYTE data[1];
} ImbRespPacket;
#define MIN_IMB_RESPONSE_SIZE 7 /* min packet + completion code */
#define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE
/************************
* ImbRequestBuffer
************************/
/*D*
// Name: ImbRequestBuffer
// Purpose: Structure definition for holding IMB message data
// Context: Used by SendTimedImbpMessage and SendTimedI2cMessge
// functions in the library interface. In use, it is overlayed on a
// char buffer of size MIN_IMB_REQ_BUF_SIZE +
// Fields:
// respBufSize size of the response buffer
//
// timeout timeout value in milli seconds
//
// req body of request to send
//
*D*/
typedef struct {
BYTE rsSa;
BYTE cmd;
BYTE netFn;
BYTE rsLun;
BYTE dataLength;
BYTE data[1];
} ImbRequest;
typedef struct {
DWORD flags; /* request flags*/
#define NO_RESPONSE_EXPECTED 0x01 /*dont wait around for an IMB response*/
DWORD timeOut; /* in uSec units*/
ImbRequest req; /* message buffer*/
} ImbRequestBuffer;
#define MIN_IMB_REQ_BUF_SIZE 13 /* a buffer without any request data*/
/************************
* ImbResponseBuffer
************************/
/*D*
// Name: ImbResponseBuffer
// Purpose: Structure definition for response of a previous send
// Context: Used by DeviceIoControl to pass the message to be sent to
// MISSMIC port
// Fields:
// cCode completion code returned by firmware
// data buffer for response data from firmware
*D*/
typedef struct {
BYTE cCode;
BYTE data[1];
} ImbResponseBuffer;
#define MIN_IMB_RESP_BUF_SIZE 1
#define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE)
#pragma pack()
/*
* Async message access structures and types
*/
typedef DWORD ImbAsyncSeq;
/*
* This is the structure passed in to IOCTL_IMB_GET_ASYNC_MSG
*/
typedef struct {
DWORD timeOut;
ImbAsyncSeq lastSeq;
} ImbAsyncRequest;
#define ASYNC_SEQ_START 0
typedef struct {
ImbAsyncSeq thisSeq;
BYTE data[1];
} ImbAsyncResponse;
#define MIN_ASYNC_RESP_SIZE sizeof( ImbAsyncSeq )
#define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
/*
** Driver Ioctls
** In Linux, these calculate to:
** IOCTL_IMB_SEND_MESSAGE =1082
** IOCTL_IMB_GET_ASYNC_MSG =1088
** IOCTL_IMB_MAP_MEMORY =108e
** IOCTL_IMB_UNMAP_MEMORY =1090
** IOCTL_IMB_SHUTDOWN_CODE =1092
** IOCTL_IMB_REGISTER_ASYNC_OBJ =1098
** IOCTL_IMB_DEREGISTER_ASYNC_OBJ=109a
** IOCTL_IMB_CHECK_EVENT =109c
** IOCTL_IMB_POLL_ASYNC =1094
*/
#define FILE_DEVICE_IMB 0x00008010
#define IOCTL_IMB_BASE 0x00000880
#define IOCTL_IMB_SEND_MESSAGE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 2), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_GET_ASYNC_MSG CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 8), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_MAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 14), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 16), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_SHUTDOWN_CODE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 18), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_REGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 24), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_DEREGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 26), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_CHECK_EVENT CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 28), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IMB_POLL_ASYNC CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 20), METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif /* IMB_IF__ */
/*----------------------------------------------------------------------*/
/* No asynchronous messages available */
#define IMB_MSG_NOT_AVAILABLE ((NTSTATUS)0xE0070012L)
#ifdef IMBLOG_H__
/* Define the facility codes */
#define FACILITY_RPC_STUBS 0x3
#define FACILITY_RPC_RUNTIME 0x2
#define FACILITY_IO_ERROR_CODE 0x4
#define IMB_IO_ERROR_CODE 0x7
#define STATUS_SEVERITY_WARNING 0x2
#define STATUS_SEVERITY_SUCCESS 0x0
#define STATUS_SEVERITY_INFORMATIONAL 0x1
#define STATUS_SEVERITY_ERROR 0x3
/* Not enough memory for internal storage of device %1. */
#define INSUFFICIENT_RESOURCES ((NTSTATUS)0xE0070001L)
#define INVALID_INPUT_BUFFER ((NTSTATUS)0xE0070002L)
#define INVALID_OUTPUT_BUFFER ((NTSTATUS)0xE0070003L)
#define IMB_SEND_TIMEOUT ((NTSTATUS)0xE0070004L)
#define IMB_RECEIVE_TIMEOUT ((NTSTATUS)0xE0070005L)
#define IMB_IF_SEND_TIMEOUT ((NTSTATUS)0xE0070006L)
#define IMB_IF_RECEIVE_TIMEOUT ((NTSTATUS)0xE0040007L)
#define HARDWARE_FAILURE ((NTSTATUS)0xE0040008L)
#define DRIVER_FAILURE ((NTSTATUS)0xE0040009L)
#define IMB_INVALID_IF_RESPONSE ((NTSTATUS)0xE004000AL)
#define IMB_INVALID_PACKET ((NTSTATUS)0xE004000BL)
#define IMB_RESPONSE_DATA_OVERFLOW ((NTSTATUS)0xE004000CL)
#define IMB_INVALID_REQUEST ((NTSTATUS)0xE007000DL)
#define INVALID_DRIVER_IOCTL ((NTSTATUS)0xE007000EL)
#define INVALID_DRIVER_REQUEST ((NTSTATUS)0xE007000FL)
#define IMB_CANT_GET_SMS_BUFFER ((NTSTATUS)0xE0070010L)
#define INPUT_BUFFER_TOO_SMALL ((NTSTATUS)0xE0070011L)
#define IMB_SEND_ERROR ((NTSTATUS)0xE0070013L)
#endif /* IMBLOG_H__ */
/*----------------------------------------------------------------------*/
#ifndef IMBAPI_H__
#define IMBAPI_H__
#include <sys/types.h>
#define WRITE_READ_I2C 0x52
#define WRITE_EMP_BUFFER 0x7a
#define GET_DEVICE_ID 0x1
#define SEND_MESSAGE 0x34
#define BMC_SA 0x20
#define BMC_LUN 0
#define APP_NETFN 0x06
#define IPMI_09_VERSION 0x90
#define IPMI_10_VERSION 0x01
#define IPMI_15_VERSION 0x51
#ifndef IPMI10_GET_DEVICE_ID_RESP_LENGTH
#define IPMI10_GET_DEVICE_ID_RESP_LENGTH 12
#endif
#define IPMB_CHANNEL 0x0
#define EMP_CHANNEL 0x1
#define LAN_CHANNEL 0x2
#define RESERVED_LUN 0x3
#define IPMB_LUN 0x2
#define EMP_LUN 0x0
#define PUBLIC_BUS 0
#define BMC_CONTROLLER 0x20
#define FPC_CONTROLLER 0x22
typedef enum {
ACCESN_OK,
ACCESN_ERROR,
ACCESN_OUT_OF_RANGE,
ACCESN_END_OF_DATA,
ACCESN_UNSUPPORTED,
ACCESN_INVALID_TRANSACTION,
ACCESN_TIMED_OUT
} ACCESN_STATUS;
#pragma pack(1)
/*
* Request structure provided to SendTimedImbpRequest()
*/
typedef struct {
unsigned char cmdType;
unsigned char rsSa;
unsigned char busType;
unsigned char netFn;
unsigned char rsLun;
unsigned char * data;
int dataLength;
} IMBPREQUESTDATA;
/*
* Request structure provided to SendTimedI2cRequest()
*/
typedef struct {
unsigned char rsSa;
unsigned char busType;
unsigned char numberOfBytesToRead;
unsigned char * data;
int dataLength;
} I2CREQUESTDATA;
#pragma pack()
/*#ifdef IMB_API
*
* This section is provided to be able to compile using imb_if.h
*
*
* function return type. This is also defined in the local instrumentation
* so we ifdef here to avoid conflict.
*/
#define METHOD_BUFFERED 0
#define FILE_ANY_ACCESS 0
/*
* This is necessary to compile using memIf.h
*/
typedef enum _INTERFACE_TYPE
{
Internal,
Isa,
Eisa,
MicroChannel,
TurboChannel,
MaximumInterfaceType
} INTERFACE_TYPE, * PINTERFACE_TYPE;
#ifdef WIN32
/* From memIf.h */
#pragma pack(1)
typedef struct
{
INTERFACE_TYPE InterfaceType; // Isa, Eisa, etc....
ULONG BusNumber; // Bus number
PHYSICAL_ADDRESS BusAddress; // Bus-relative address
ULONG AddressSpace; // 0 is memory, 1 is I/O
ULONG Length; // Length of section to map
} PHYSICAL_MEMORY_INFO, * PPHYSICAL_MEMORY_INFO;
#pragma pack()
#endif
/*#else // not IMB_API */
/*
* These are defined in imb_if.h but are needed by users of the imbapi library
*/
#define ASYNC_SEQ_START 0
/*
* This is the generic IMB packet format, the final checksum cant be
* represented in this structure and will show up as the last data byte
*/
/*
#define MIN_IMB_PACKET_SIZE 7
#define MAX_IMB_PACKET_SIZE 33
*/
#define MAX_BUFFER_SIZE 64
/*#endif // IMB_API */
/******************************
* FUNCTION PROTOTYPES
******************************/
ACCESN_STATUS
SendTimedImbpRequest (
IMBPREQUESTDATA *reqPtr,
int timeOut,
BYTE * respDataPtr,
int * respDataLen,
BYTE * completionCode
);
ACCESN_STATUS
SendTimedI2cRequest (
I2CREQUESTDATA *reqPtr,
int timeOut,
BYTE * respDataPtr,
int * respDataLen,
BYTE * completionCode
);
ACCESN_STATUS
SendAsyncImbpRequest (
IMBPREQUESTDATA *reqPtr,
BYTE * seqNo
);
ACCESN_STATUS
GetAsyncImbpMessage (
ImbPacket * msgPtr,
DWORD * msgLen,
DWORD timeOut,
ImbAsyncSeq * seqNo,
DWORD channelNumber
);
ACCESN_STATUS
GetAsyncImbpMessage_Ex (
ImbPacket * msgPtr,
DWORD * msgLen,
DWORD timeOut,
ImbAsyncSeq * seqNo,
DWORD channelNumber,
BYTE * sessionHandle,
BYTE * privilege
);
ACCESN_STATUS
UnmapPhysicalMemory( int virtualAddress, int Length );
ACCESN_STATUS
StartAsyncMesgPoll(void);
ACCESN_STATUS
MapPhysicalMemory (
int startAddress,
int addressLength,
int *virtualAddress
);
ACCESN_STATUS
SetShutDownCode (
int delayTime,
int code
);
ACCESN_STATUS
SendTimedEmpMessageResponse (
ImbPacket * ptr,
char *responseDataBuf,
int responseDataLen,
int timeOut
);
ACCESN_STATUS
SendTimedEmpMessageResponse_Ex (
ImbPacket * ptr,
char *responseDataBuf,
int responseDataLen,
int timeOut,
BYTE sessionHandle,
BYTE channelNumber
);
ACCESN_STATUS
SendTimedLanMessageResponse (
ImbPacket * ptr,
char *responseDataBuf,
int responseDataLen,
int timeOut
);
ACCESN_STATUS
SendTimedLanMessageResponse_Ex (
ImbPacket * ptr,
char *responseDataBuf,
int responseDataLen,
int timeOut ,
BYTE sessionHandle,
BYTE channelNumber
);
ACCESN_STATUS
IsAsyncMessageAvailable (unsigned int eventId );
ACCESN_STATUS
RegisterForImbAsyncMessageNotification (unsigned int *handleId);
ACCESN_STATUS
UnRegisterForImbAsyncMessageNotification (unsigned int handleId,int iFlag);
BYTE GetIpmiVersion(void);
#endif /* IMBAPI_H__ */

View File

@ -36,92 +36,141 @@
#include <stdio.h>
#include <stdlib.h>
#include <ltdl.h>
#include <string.h>
#include <config.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi.h>
extern struct static_intf static_intf_list[];
#ifdef IPMI_INTF_OPEN
extern struct ipmi_intf ipmi_open_intf;
#endif
#ifdef IPMI_INTF_IMB
extern struct ipmi_intf ipmi_imb_intf;
#endif
#ifdef IPMI_INTF_LIPMI
extern struct ipmi_intf ipmi_lipmi_intf;
#endif
#ifdef IPMI_INTF_LAN
extern struct ipmi_intf ipmi_lan_intf;
#endif
#ifdef IPMI_INTF_LANPLUS
extern struct ipmi_intf ipmi_lanplus_intf;
#endif
/* ipmi_intf_init
* initialize dynamic plugin interface
*/
int ipmi_intf_init(void)
struct ipmi_intf * ipmi_intf_table[] = {
#ifdef IPMI_INTF_OPEN
&ipmi_open_intf,
#endif
#ifdef IPMI_INTF_IMB
&ipmi_imb_intf,
#endif
#ifdef IPMI_INTF_LIPMI
&ipmi_lipmi_intf,
#endif
#ifdef IPMI_INTF_LAN
&ipmi_lan_intf,
#endif
#ifdef IPMI_INTF_LANPLUS
&ipmi_lanplus_intf,
#endif
NULL
};
void ipmi_intf_print(void)
{
if (lt_dlinit() < 0) {
printf("ERROR: Unable to initialize ltdl\n");
return -1;
}
struct ipmi_intf ** intf;
int def = 1;
if (lt_dlsetsearchpath(PLUGIN_PATH) < 0) {
printf("ERROR: Unable to set ltdl plugin path to %s\n",
PLUGIN_PATH);
lt_dlexit();
return -1;
}
printf("Interfaces:\n");
return 0;
for (intf = ipmi_intf_table; intf && *intf; intf++) {
printf("\t%-12s %s", (*intf)->name, (*intf)->desc);
if (def) {
printf(" [default]");
def = 0;
}
printf("\n");
}
printf("\n");
}
/* ipmi_intf_exit
* close dynamic plugin interface
*/
void ipmi_intf_exit(void)
{
if (lt_dlexit() < 0)
printf("ERROR: Unable to cleanly exit ltdl\n");
}
/* ipmi_intf_load
* name: interface plugin name to load
/* Load an interface from the interface table above
* If no interface name is given return first entry
*/
struct ipmi_intf * ipmi_intf_load(char * name)
{
lt_dlhandle handle;
struct ipmi_intf * intf;
int (*setup)(struct ipmi_intf ** intf);
struct static_intf *i = static_intf_list;
char libname[16];
struct ipmi_intf ** intf;
struct ipmi_intf * i;
while (i->name) {
if (!strcmp(name, i->name)) {
if (i->setup(&intf) < 0) {
printf("ERROR: Unable to setup static interface %s\n", name);
if (!name) {
i = ipmi_intf_table[0];
if (i->setup && (i->setup(i) < 0)) {
printf("ERROR: Unable to setup interface %s\n", name);
return NULL;
}
return i;
}
for (intf = ipmi_intf_table; intf && *intf ; intf++) {
i = *intf;
if (!strncmp(name, i->name, strlen(name))) {
if (i->setup && (i->setup(i) < 0)) {
printf("ERROR: Unable to setup interface %s\n", name);
return NULL;
}
return intf;
return i;
}
i++;
}
memset(libname, 0, 16);
if (snprintf(libname, sizeof(libname), "lib%s", name) <= 0) {
printf("ERROR: Unable to find plugin '%s' in '%s'\n",
name, PLUGIN_PATH);
return NULL;
}
handle = lt_dlopenext(libname);
if (handle == NULL) {
printf("ERROR: Unable to find plugin '%s' in '%s'\n",
libname, PLUGIN_PATH);
return NULL;
}
setup = lt_dlsym(handle, "intf_setup");
if (!setup) {
printf("ERROR: Unable to find interface setup symbol in plugin %s\n", name);
lt_dlclose(handle);
return NULL;
}
if (setup(&intf) < 0) {
printf("ERROR: Unable to run interface setup for plugin %s\n", name);
lt_dlclose(handle);
return NULL;
}
return intf;
return NULL;
}
void ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
{
if (intf && intf->session) {
memset(intf->session->hostname, 0, 16);
if (hostname)
memcpy(intf->session->hostname, hostname, min(strlen(hostname), 64));
}
}
void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
{
if (intf && intf->session) {
memset(intf->session->username, 0, 16);
if (username)
memcpy(intf->session->username, username, min(strlen(username), 16));
}
}
void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
{
if (intf && intf->session) {
memset(intf->session->authcode, 0, sizeof(intf->session->authcode));
intf->session->password = 0;
if (password) {
intf->session->password = 1;
memcpy(intf->session->authcode,
password,
min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
}
}
}
void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, unsigned char level)
{
if (intf && intf->session)
intf->session->privlvl = level;
}
void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
{
if (intf && intf->session)
intf->session->port = port;
}
void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, unsigned char authtype)
{
if (intf && intf->session)
intf->session->authtype_set = authtype;
}

View File

@ -32,16 +32,12 @@
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
MAINTAINERCLEANFILES = Makefile.in
plugindir = $(pluginpath)
INCLUDES = -I$(top_srcdir)/include
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_lan.la
plugin_LTLIBRARIES = @PLUGIN_INTF_LAN@
noinst_LTLIBRARIES = @STATIC_INTF_LAN@
libintf_lan_la_LDFLAGS = @LDFLAGS_INTF_LAN@
libintf_lan_la_LIBADD = $(top_srcdir)/lib/libipmitool.la
libintf_lan_la_SOURCES = lan.c lan.h asf.h rmcp.h md5.c md5.h
noinst_LTLIBRARIES = @INTF_LAN_LIB@
libintf_lan_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_lan_la_SOURCES = lan.c lan.h asf.h rmcp.h auth.c auth.h md5.c md5.h

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <ipmitool/helper.h>
#include <ipmitool/bswap.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#if HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_CRYPTO_MD2
# include <openssl/md2.h>
#endif
#ifdef HAVE_CRYPTO_MD5
# include <openssl/md5.h>
#else
# include "md5.h"
#endif
/*
* multi-session authcode generation for MD5
* H(password + session_id + msg + session_seq + password)
*
* Use OpenSSL implementation of MD5 algorithm if found
*/
unsigned char * ipmi_auth_md5(struct ipmi_session * s, unsigned char * data, int data_len)
{
#ifdef HAVE_CRYPTO_MD5
MD5_CTX ctx;
static unsigned char md[16];
uint32_t temp;
#if WORDS_BIGENDIAN
temp = BSWAP_32(s->in_seq);
#else
temp = s->in_seq;
#endif
memset(md, 0, 16);
memset(&ctx, 0, sizeof(MD5_CTX));
MD5_Init(&ctx);
MD5_Update(&ctx, (const unsigned char *)s->authcode, 16);
MD5_Update(&ctx, (const unsigned char *)&s->session_id, 4);
MD5_Update(&ctx, (const unsigned char *)data, data_len);
MD5_Update(&ctx, (const unsigned char *)&temp, sizeof(uint32_t));
MD5_Update(&ctx, (const unsigned char *)s->authcode, 16);
MD5_Final(md, &ctx);
if (verbose > 3)
printf(" MD5 AuthCode : %s\n", buf2str(md, 16));
return md;
#else /*HAVE_CRYPTO_MD5*/
md5_state_t state;
static md5_byte_t digest[16];
uint32_t temp;
memset(digest, 0, 16);
memset(&state, 0, sizeof(md5_state_t));
md5_init(&state);
md5_append(&state, (const md5_byte_t *)s->authcode, 16);
md5_append(&state, (const md5_byte_t *)&s->session_id, 4);
md5_append(&state, (const md5_byte_t *)data, data_len);
#if WORDS_BIGENDIAN
temp = BSWAP_32(s->in_seq);
#else
temp = s->in_seq;
#endif
md5_append(&state, (const md5_byte_t *)&temp, 4);
md5_append(&state, (const md5_byte_t *)s->authcode, 16);
md5_finish(&state, digest);
if (verbose > 3)
printf(" MD5 AuthCode : %s\n", buf2str(digest, 16));
return digest;
#endif /*HAVE_CRYPTO_MD5*/
}
/*
* multi-session authcode generation for MD2
* H(password + session_id + msg + session_seq + password)
*
* Use OpenSSL implementation of MD2 algorithm if found.
* This function is analogous to ipmi_auth_md5
*/
unsigned char * ipmi_auth_md2(struct ipmi_session * s, unsigned char * data, int data_len)
{
#ifdef HAVE_CRYPTO_MD2
MD2_CTX ctx;
static unsigned char md[16];
uint32_t temp;
#if WORDS_BIGENDIAN
temp = BSWAP_32(s->in_seq);
#else
temp = s->in_seq;
#endif
memset(md, 0, 16);
memset(&ctx, 0, sizeof(MD2_CTX));
MD2_Init(&ctx);
MD2_Update(&ctx, (const unsigned char *)s->authcode, 16);
MD2_Update(&ctx, (const unsigned char *)&s->session_id, 4);
MD2_Update(&ctx, (const unsigned char *)data, data_len);
MD2_Update(&ctx, (const unsigned char *)&temp, sizeof(uint32_t));
MD2_Update(&ctx, (const unsigned char *)s->authcode, 16);
MD2_Final(md, &ctx);
if (verbose > 3)
printf(" MD2 AuthCode : %s\n", buf2str(md, 16));
return md;
#else /*HAVE_CRYPTO_MD2*/
static unsigned char md[16];
memset(md, 0, 16);
printf("WARNING: No internal support for MD2! "
"Please re-compile with OpenSSL.\n");
return md;
#endif /*HAVE_CRYPTO_MD2*/
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_AUTH_H
#define IPMI_AUTH_H
unsigned char * ipmi_auth_md2(struct ipmi_session * s, unsigned char * data, int data_len);
unsigned char * ipmi_auth_md5(struct ipmi_session * s, unsigned char * data, int data_len);
#endif /*IPMI_AUTH_H*/

File diff suppressed because it is too large Load Diff

View File

@ -38,37 +38,24 @@
#define IPMI_LAN_H
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#define IPMI_LAN_CHANNEL_1 0x07
#define IPMI_LAN_CHANNEL_2 0x06
#define IPMI_LAN_CHANNEL_E 0x0e
#define IPMI_LAN_PORT 0x26f
#define IPMI_SESSION_AUTHTYPE_NONE 0x0
#define IPMI_SESSION_AUTHTYPE_MD2 0x1
#define IPMI_SESSION_AUTHTYPE_MD5 0x2
#define IPMI_SESSION_AUTHTYPE_KEY 0x4
#define IPMI_SESSION_AUTHTYPE_OEM 0x5
#define IPMI_LAN_TIMEOUT 2
#define IPMI_LAN_RETRY 4
#define IPMI_SESSION_PRIV_CALLBACK 0x1
#define IPMI_SESSION_PRIV_USER 0x2
#define IPMI_SESSION_PRIV_OPERATOR 0x3
#define IPMI_SESSION_PRIV_ADMIN 0x4
#define IPMI_SESSION_PRIV_OEM 0x5
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_vals[];
extern struct ipmi_session lan_session;
unsigned char * ipmi_auth_md5(unsigned char * data, int data_len);
unsigned char ipmi_csum(unsigned char * d, int s);
struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_lan_open(struct ipmi_intf * intf, char * hostname, int port, char * username, char * password);
int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
int ipmi_lan_open(struct ipmi_intf * intf);
void ipmi_lan_close(struct ipmi_intf * intf);
void ipmi_get_channel_info(struct ipmi_intf * intf, unsigned char channel);
int ipmi_lan_ping(struct ipmi_intf * intf);
int lan_intf_setup(struct ipmi_intf ** intf);
struct ipmi_intf ipmi_lan_intf;
extern struct ipmi_intf ipmi_lan_intf;
#endif /*IPMI_LAN_H*/

View File

@ -0,0 +1,49 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_lanplus.la
noinst_LTLIBRARIES = @INTF_LANPLUS_LIB@
libintf_lanplus_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_lanplus_la_SOURCES = \
rmcp.h asf.h \
lanplus.c lanplus.h \
lanplus_strings.c \
lanplus_crypt.c lanplus_crypt.h \
lanplus_dump.h lanplus_dump.c \
lanplus_crypt_impl.h lanplus_crypt_impl.c

View File

@ -0,0 +1,74 @@
This interface exists to provide a means of connecting to an IPMIv2 enabled
BMC. In some places, the IPMIv2 specification is either unclear or
inconsistent, and interpretations of the intent of the specification had to
be made at the discretion of the implementor. The purpose of this
document is to make those decisions clear so that 1) they can be reviewed
by others and 2) so that the rationale for those decisions can be made
clear.
* Though it's not stated explicitly with which algorithm the K1 and K2 keys
should be generated, we chose to use the authentication algorithm. The
specification states that K1 and K2 are generated with an HMAC algorithm,
and all of the authentication algorithms (except for "none") are HMAC
algorithms, whereas the integrity algorithms are not all HMAC. See section
13.32 for details about K1 and K2, and section
* The IPMIv2 specification describes a key, Kg, that is the "BMC key".
This key functions as a global key that is required to be known in addition
to the user's key, by authenticating users. If the BMC has a null Kg, the
users key, Kuid, is used in its place in algorithms where Kg is required,
per the specification section 13.33. A user can obtain the status of Kg by
querying the BMC with the Get Channel Authentication Capabilities command.
Currently, this implementation does not provide a way for a user to specify
Kg for BMCs that require it.
* The specification is unclear as to which key is used for HMAC based
integrity checking. One the one hand, section 13.28.4 states explicitly
that HMAC integrity algorithms use the session integrity key as the HMAC
key. Confusing that matter is a statement in section 13.32 regarding the
creation of additional keying material. In this section it is stated that
"all keying material for the RSP integrity and confidentiality algorithms
will be generated by processing a pre-defined set of constants using HMAC
per [RFC2104], keyed by sik". And "For the mandatory-to-implement
integrity and confidentiality algorithms defined in this specification,
processing the first two (2) constants will generate the require amount of
keying material." We decided to use K1 as our HMAC key for the generation
of authentication codes (integrity checking). Furthermore, we are using
all 20 bytes of K1.
* IPMIv2 compliant BMCs are supposed to support 20 byte passwords, as well
store metadata describing whether the password was stored as a 16 byte or
20 byte class password. We do not currently support 20 byte passwords. It
should be noted that there are obvious mistakes in the SET USER PASSWORD
command specification, as it mentions the ability to query for 16/20 byte
password status, but the packet format does not support this.
* The IPMIv2 specification describes a type of login called a "role only
login." This feature allows a user to login providing only a requested
privilege level and a password. We do not currently support this feature.
Supporting this feature would only require the ability to specify
username/privilege lookups in the RAKP 1 message sent from ipmitool. We
currently specify the use of username only lookups for authentication.
* In the IPMIv2 packet description in table 13-8 of the IPMv2
specification, there are two fields that are rather ambiguous in meaning.
The fields are "Pad Length" and "Next Header". Although neither field is
listed as belonging to the IPMIv2 packet format, we include/expect them
both in our IPMIv2 packets. Are rationale is 1) the Next Headers field's
comment states what the value of that field should be for IPMIv2, and 2)
for the most part the ASF and IPMIv2 fields seem to parallel each other,
and we feel that the Pad Length and Next Header fields were left out of the
IPMIv2 column by mistake.
* The GET CHANNEL CIPHER SUITES command documentation seems to have
mistakes. The "start of record" byte is stated to be either 0x30 or 0x31,
whereas the detailed description in table 22-18 leads us to believe that
this byte should really be 0xC0 or 0xC1. Also the description of bits 5:0
in the start of record byte should probably be 00_0000 rather than 00_000.

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_ASF_H
#define IPMI_ASF_H
#include <ipmitool/helper.h>
#include "lanplus.h"
#define ASF_RMCP_IANA 0x000011be
#define ASF_TYPE_PING 0x80
#define ASF_TYPE_PONG 0x40
static const struct valstr asf_type_vals[] __attribute__((unused)) = {
{ 0x10, "Reset" },
{ 0x11, "Power-up" },
{ 0x12, "Unconditional Power-down" },
{ 0x13, "Power Cycle" },
{ 0x40, "Presence Pong" },
{ 0x41, "Capabilities Response" },
{ 0x42, "System State Response" },
{ 0x80, "Presence Ping" },
{ 0x81, "Capabilities Request" },
{ 0x82, "System State Request" },
{ 0x00, NULL }
};
/* ASF message header */
struct asf_hdr {
unsigned long iana;
unsigned char type;
unsigned char tag;
unsigned char __reserved;
unsigned char len;
} __attribute__((packed));
int handle_asf(struct ipmi_intf * intf, unsigned char * data, int data_len);
#endif /* IPMI_ASF_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_H
#define IPMI_LANPLUS_H
#include <ipmitool/ipmi.h>
#define IPMI_LANPLUS_PORT 0x26f
/*
* RAKP return codes. These values come from table 13-15 of the IPMI v2
* specification.
*/
#define IPMI_RAKP_STATUS_NO_ERRORS 0x00
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION 0x01
#define IPMI_RAKP_STATUS_INVALID_SESSION_ID 0x02
#define IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE 0x03
#define IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM 0x04
#define IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM 0x05
#define IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD 0x06
#define IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD 0x07
#define IPMI_RAKP_STATUS_INACTIVE_SESSION_ID 0x08
#define IPMI_RAKP_STATUS_INVALID_ROLE 0x09
#define IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED 0x0A
#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE 0x0B
#define IPMI_RAKP_STATUS_INVALID_NAME_LENGTH 0x0C
#define IPMI_RAKP_STATUS_UNAUTHORIZED_NAME 0x0D
#define IPMI_RAKP_STATUS_UNAUTHORIZED_GUID 0x0E
#define IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE 0x0F
#define IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM 0x10
#define IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH 0x11
#define IPMI_RAKP_STATUS_ILLEGAL_PARAMTER 0x12
#define IPMI_LAN_CHANNEL_1 0x07
#define IPMI_LAN_CHANNEL_2 0x06
#define IPMI_LAN_CHANNEL_E 0x0e
#define IPMI_LAN_TIMEOUT 2
#define IPMI_LAN_RETRY 4
#define IPMI_PRIV_CALLBACK 1
#define IPMI_PRIV_USER 2
#define IPMI_PRIV_OPERATOR 3
#define IPMI_PRIV_ADMIN 4
#define IPMI_PRIV_OEM 5
/* From table 13-17 of the IPMI v2 specification */
#define IPMI_AUTH_RAKP_NONE 0x00
#define IPMI_AUTH_RAKP_HMAC_SHA1 0x01
#define IPMI_AUTH_RAKP_HMAC_MD5 0x02
/* From table 13-18 of the IPMI v2 specification */
#define IPMI_INTEGRITY_NONE 0x00
#define IPMI_INTEGRITY_HMAC_SHA1_96 0x01
#define IPMI_INTEGRITY_HMAC_MD5_128 0x02
#define IPMI_INTEGRITY_MD5_128 0x03
/* From table 13-19 of the IPMI v2 specfication */
#define IPMI_CRYPT_NONE 0x00
#define IPMI_CRYPT_AES_CBC_128 0x01
#define IPMI_CRYPT_XRC4_128 0x02
#define IPMI_CRYPT_XRC4_40 0x03
#define IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE 0x10
/* Session message offsets, from table 13-8 of the v2 specification */
#define IMPI_LANPLUS_OFFSET_AUTHTYPE 0x04
#define IMPI_LANPLUS_OFFSET_PAYLOAD_TYPE 0x05
#define IMPI_LANPLUS_OFFSET_SESSION_ID 0x06
#define IMPI_LANPLUS_OFFSET_SEQUENCE_NUM 0x0A
#define IMPI_LANPLUS_OFFSET_PAYLOAD_SIZE 0x0E
#define IPMI_LANPLUS_OFFSET_PAYLOAD 0x10
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
/*
* TODO: these are wild guesses and should be checked
*/
#define IPMI_MAX_CONF_HEADER_SIZE 0x20
#define IPMI_MAX_PAYLOAD_SIZE 0xFF /* Includes confidentiality header/trailer */
#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20
#define IPMI_MAX_AUTH_CODE_SIZE 0x20
#define IPMI_REQUEST_MESSAGE_SIZE 0x07
#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */
#define IPMI_SHA1_AUTHCODE_SIZE 0x0C
/*
*This is accurate, as long as we're only passing 1 auth algorithm,
* one integrity algorithm, and 1 encyrption alogrithm
*/
#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
#define IPMI_RAKP1_MESSAGE_SIZE 43
#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28
#define IPMI_MAX_USER_NAME_LENGTH 16
extern const struct valstr ipmi_privlvl_vals[];
extern const struct valstr ipmi_authtype_vals[];
extern struct ipmi_intf ipmi_lanplus_intf;
struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_lanplus_open(struct ipmi_intf * intf);
void ipmi_lanplus_close(struct ipmi_intf * intf);
int ipmiv2_lan_ping(struct ipmi_intf * intf);
#endif /*IPMI_LAN_H*/

View File

@ -0,0 +1,876 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <assert.h>
#include <string.h>
#include <config.h>
#include <ipmitool/bswap.h>
#include "lanplus.h"
#include "lanplus_crypt.h"
#include "lanplus_crypt_impl.h"
/*
* lanplus_rakp2_hmac_matches
*
* param session holds all the state data that we need to generate the hmac
* param hmac is the HMAC sent by the BMC in the RAKP 2 message
*
* The HMAC was generated [per RFC2404] from :
*
* SIDm - Remote console session ID
* SIDc - BMC session ID
* Rm - Remote console random number
* Rc - BMC random number
* GUIDc - BMC guid
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <UNAMEm> - Username (absent for null user names)
*
* generated by using Kuid. I am aware that the subscripts on the values
* look backwards, but that's the way they are written in the specification.
*
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
*
* return 0 on success (the authcode matches)
* 1 on failure (the authcode does not match)
*/
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const unsigned char * bmc_mac)
{
char * buffer;
int bufferLength, i;
unsigned char mac[20];
int macLength;
unsigned int SIDm_lsbf, SIDc_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 1;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
bufferLength =
4 + /* SIDm */
4 + /* SIDc */
16 + /* Rm */
16 + /* Rc */
16 + /* GUIDc */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username); /* optional */
buffer = malloc(bufferLength);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* SIDm */
SIDm_lsbf = session->v2_data.console_id;
#if WORDS_BIGENDIAN
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
#endif
memcpy(buffer, &SIDm_lsbf, 4);
/* SIDc */
SIDc_lsbf = session->v2_data.bmc_id;
#if WORDS_BIGENDIAN
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
#endif
memcpy(buffer + 4, &SIDc_lsbf, 4);
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[8 + i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[8 + i] = session->v2_data.console_rand[i];
#endif
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[24 + i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[24 + i] = session->v2_data.bmc_rand[i];
#endif
/* GUIDc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[40 + i] = session->v2_data.bmc_guid[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[40 + i] = session->v2_data.bmc_guid[i];
#endif
/* ROLEm */
buffer[56] = session->v2_data.requested_role;
/* ULENGTHm */
buffer[57] = strlen(session->username);
/* UserName [optional] */
for (i = 0; i < buffer[57]; ++i)
buffer[58 + i] = session->username[i];
if (verbose > 2)
{
printbuf(buffer, bufferLength, ">> rakp2 mac input buffer");
printbuf((char*)(session->authcode), IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp2 mac key");
}
/*
* The buffer is complete. Let's hash.
*/
lanplus_HMAC(session->v2_data.auth_alg,
session->authcode,
(session->authcode[IPMI_AUTHCODE_BUFFER_SIZE] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE),
buffer,
bufferLength,
mac,
&macLength);
free(buffer);
if (verbose > 2)
{
printbuf(mac, macLength, ">> rakp2 mac as computed by the remote console");
}
return (memcmp(bmc_mac, mac, macLength) == 0);
}
/*
* lanplus_rakp4_hmac_matches
*
* param session holds all the state data that we need to generate the hmac
* param hmac is the HMAC sent by the BMC in the RAKP 4 message
*
* The HMAC was generated [per RFC2404] from :
*
* Rm - Remote console random number
* SIDc - BMC session ID
* GUIDc - BMC guid
*
* generated by using SIK (the session integrity key). I am aware that the
* subscripts on the values look backwards, but that's the way they are
* written in the specification.
*
* If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
*
* return 0 on success (the authcode matches)
* 1 on failure (the authcode does not match)
*/
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const unsigned char * bmc_mac)
{
char * buffer;
int bufferLength, i;
unsigned char mac[20];
int macLength;
unsigned int SIDc_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 1;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
bufferLength =
16 + /* Rm */
4 + /* SIDc */
16; /* GUIDc */
buffer = (char*)malloc(bufferLength);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[i] = session->v2_data.console_rand[i];
#endif
/* SIDc */
SIDc_lsbf = session->v2_data.bmc_id;
#if WORDS_BIGENDIAN
SIDc_lsbf = BSWAP_32(SIDc_lsbf);
#endif
memcpy(buffer + 16, &SIDc_lsbf, 4);
/* GUIDc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
buffer[i + 20] = session->v2_data.bmc_guid[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
buffer[i + 20] = session->v2_data.bmc_guid[i];
#endif
if (verbose > 2)
{
printbuf(buffer, bufferLength, ">> rakp4 mac input buffer");
printbuf(session->v2_data.sik, 20l, ">> rakp4 mac key (sik)");
}
/*
* The buffer is complete. Let's hash.
*/
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20,
buffer,
bufferLength,
mac,
&macLength);
if (verbose > 2)
{
printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console");
}
free(buffer);
assert(macLength == 20);
return (memcmp(bmc_mac, mac, 12) == 0);
}
/*
* lanplus_generate_rakp3_auth_code
*
* This auth code is an HMAC generated with :
*
* Rc - BMC random number
* SIDm - Console session ID
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <USERNAME> - Usename (absent for null usernames)
*
* The key used to generated the MAC is Kuid
*
* I am aware that the subscripts look backwards, but that is the way they are
* written in the spec.
*
* param output_buffer [out] will hold the generated MAC
* param session [in] holds all the state data we need to generate the auth code
* param mac_length [out] will be set to the length of the auth code
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_rakp3_authcode(char * output_buffer,
const struct ipmi_session * session,
unsigned int * mac_length)
{
int ret = 0;
int input_buffer_length, i;
char * input_buffer;
unsigned int SIDm_lsbf;
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
{
*mac_length = 0;
return 0;
}
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
input_buffer_length =
16 + /* Rc */
4 + /* SIDm */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username);
input_buffer = malloc(input_buffer_length);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.bmc_rand[i];
#endif
/* SIDm */
SIDm_lsbf = session->v2_data.console_id;
#if WORDS_BIGENDIAN
SIDm_lsbf = BSWAP_32(SIDm_lsbf);
#endif
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
/* ROLEm */
input_buffer[20] = session->v2_data.requested_role;
/* ULENGTHm */
input_buffer[21] = strlen(session->username);
/* USERNAME */
for (i = 0; i < input_buffer[21]; ++i)
input_buffer[22 + i] = session->username[i];
if (verbose > 2)
{
printbuf(input_buffer, input_buffer_length, ">> rakp3 mac input buffer");
printbuf((char*)(session->authcode), IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp3 mac key");
}
lanplus_HMAC(session->v2_data.auth_alg,
session->authcode,
(session->authcode[IPMI_AUTHCODE_BUFFER_SIZE - 1] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE),
input_buffer,
input_buffer_length,
output_buffer,
mac_length);
if (verbose > 2)
printbuf(output_buffer, *mac_length, "generated rakp3 mac");
free(input_buffer);
return ret;
}
/*
* lanplus_generate_sik
*
* Generate the session integrity key (SIK) used for integrity checking
* during the IPMI v2 / RMCP+ session
*
* This session integrity key is a HMAC generated with :
*
* Rm - Console generated random number
* Rc - BMC generated random number
* ROLEm - Requested privilege level (entire byte)
* ULENGTHm - Username length
* <USERNAME> - Usename (absent for null usernames)
*
* The key used to generated the SIK is Kg if Kg is not null (two-key logins are
* enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
* the SIK.
*
* I am aware that the subscripts look backwards, but that is the way they are
* written in the spec.
*
* param session [in/out] contains our input and output fields.
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_sik(struct ipmi_session * session)
{
char * input_buffer;
int input_buffer_length, i;
char * input_key;
int input_key_length;
int mac_length;
memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
return 0;
/* We don't yet support other alogrithms */
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
input_buffer_length =
16 + /* Rm */
16 + /* Rc */
1 + /* ROLEm */
1 + /* ULENGTHm */
strlen(session->username);
input_buffer = malloc(input_buffer_length);
/*
* Fill the buffer. I'm assuming that we're using the LSBF representation of the
* multibyte numbers in use.
*/
/* Rm */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.console_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[i] = session->v2_data.console_rand[i];
#endif
/* Rc */
#if WORDS_BIGENDIAN
for (i = 0; i < 16; ++i)
input_buffer[16 + i] = session->v2_data.bmc_rand[16 - 1 - i];
#else
for (i = 0; i < 16; ++i)
input_buffer[16 + i] = session->v2_data.bmc_rand[i];
#endif
/* ROLEm */
input_buffer[32] = session->v2_data.requested_role;
/* ULENGTHm */
input_buffer[33] = strlen(session->username);
/* USERNAME */
for (i = 0; i < input_buffer[33]; ++i)
input_buffer[34 + i] = session->username[i];
if (session->v2_data.kg[0])
{
/* We will be hashing with Kg */
/*
* TODO: Section 13.31 of the IPMI v2 spec describes the SIK creation
* using Kg. It specifies that Kg should not be truncated, but I
* do not know what is meant by that.
*/
printf("lanplus_generate_sik: We dont yet support hashing with Kg");
assert(0);
input_key = session->v2_data.kg;
input_key_length = strlen(session->v2_data.kg);
}
else
{
/* We will be hashing with Kuid */
input_key = session->authcode;
input_key_length = (session->authcode[IPMI_AUTHCODE_BUFFER_SIZE - 1] == 0?
strlen(session->authcode): IPMI_AUTHCODE_BUFFER_SIZE);
}
lanplus_HMAC(session->v2_data.auth_alg,
input_key,
input_key_length,
input_buffer,
input_buffer_length,
session->v2_data.sik,
&mac_length);
free(input_buffer);
assert(mac_length == 20);
/*
* The key MAC generated is 20 bytes, but we will only be using the first
* 12 for SHA1 96
*/
if (verbose >= 2)
printbuf(session->v2_data.sik, 20, "Generated session integrity key");
return 0;
}
/*
* lanplus_generate_k1
*
* Generate K1, the key presumably used to generate integrity authcodes
*
* We use the authentication algorithm to generated the HMAC, using
* the session integrity key (SIK) as our key.
*
* param session [in/out].
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k1(struct ipmi_session * session)
{
unsigned int mac_length;
unsigned char CONST_1[] =
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
memcpy(session->v2_data.k1, CONST_1, 20);
else
{
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20, /* SIK length */
CONST_1,
20,
session->v2_data.k1,
&mac_length);
assert(mac_length == 20);
}
if (verbose >= 2)
printbuf(session->v2_data.k1, 20, "Generated K1");
return 0;
}
/*
* lanplus_generate_k2
*
* Generate K2, the key used for RMCP+ AES encryption.
*
* We use the authentication algorithm to generated the HMAC, using
* the session integrity key (SIK) as our key.
*
* param session [in/out].
*
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k2(struct ipmi_session * session)
{
unsigned int mac_length;
unsigned char CONST_2[] =
{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
memcpy(session->v2_data.k2, CONST_2, 20);
else
{
lanplus_HMAC(session->v2_data.auth_alg,
session->v2_data.sik,
20, /* SIK length */
CONST_2,
20,
session->v2_data.k2,
&mac_length);
assert(mac_length == 20);
}
if (verbose >= 2)
printbuf(session->v2_data.k2, 20, "Generated K2");
return 0;
}
/*
* lanplus_encrypt_payload
*
* Perform the appropriate encryption on the input data. Output the encrypted
* data to output, including the required confidentiality header and trailer.
* If the crypt_alg is IPMI_CRYPT_NONE, simply copy the input to the output and
* set bytes_written to input_length.
*
* param crypt_alg specifies the encryption algorithm (from table 13-19 of the
* IPMI v2 spec)
* param key is the used as input to the encryption algorithmf
* param input is the input data to be encrypted
* param input_length is the length of the input data to be encrypted
* param output is the cipher text generated by the encryption process
* param bytes_written is the number of bytes written during the encryption
* process
*
* returns 0 on success
* 1 on failure
*/
int lanplus_encrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * bytes_written)
{
unsigned char * padded_input;
unsigned int mod, i, bytes_encrypted;
unsigned char pad_length = 0;
if (crypt_alg == IPMI_CRYPT_NONE)
{
printf("NOT ENCRYPTING\n");
/* Just copy the input to the output */
*bytes_written = input_length;
return 0;
}
/* Currently, we only support AES */
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
assert(input_length <= 255);
/*
* The input to the AES encryption algorithm has to be a multiple of the
* block size (16 bytes). The extra byte we are adding is the pad length
* byte.
*/
mod = (input_length + 1) % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE;
if (mod)
pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
padded_input = (unsigned char*)malloc(input_length + pad_length + 1);
memcpy(padded_input, input, input_length);
/* add the pad */
for (i = 0; i < pad_length; ++i)
padded_input[input_length + i] = i + 1;
/* add the pad length */
padded_input[input_length + pad_length] = pad_length;
/* Generate an initialization vector, IV, for the encryption process */
if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
{
printf("lanplus_encrypt_payload: Error generating IV\n");
assert(0);
return 1;
}
if (verbose > 2)
printbuf(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, ">> Initialization vector");
lanplus_encrypt_aes_cbc_128(output, /* IV */
key, /* K2 */
padded_input, /* Data to encrypt */
input_length + pad_length + 1, /* Input length */
output + IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* output */
&bytes_encrypted); /* bytes written */
*bytes_written =
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE + /* IV */
bytes_encrypted;
free(padded_input);
return 0;
}
/*
* lanplus_has_valid_auth_code
*
* Determine whether the packets authcode field is valid for packet.
*
* We always return success if any of the following are true.
* - this is not an IPMIv2 packet
* - the session is not yet active
* - the packet specifies that it is not authenticated
* - the integrity algorithm agreed upon during session creation is "none"
*
* The authcode is computed using the specified integrity algorithm starting
* with the AuthType / Format field, and ending with the field immediately
* preceeding the authcode itself.
*
* The key key used to generate the authcode MAC is K1.
*
* param rs holds the response structure.
* param session holds our session state, including our chosen algorithm, key, etc.
*
* returns 1 on success (authcode is valid)
* 0 on failure (autchode integrity check failed)
*/
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
struct ipmi_session * session)
{
unsigned char * bmc_authcode;
unsigned char generated_authcode[IPMI_MAX_MAC_SIZE];
unsigned int generated_authcode_length;
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
(session->v2_data.session_state != LANPLUS_STATE_ACTIVE) ||
(! rs->session.bAuthenticated) ||
(session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
return 1;
/* We only support SHA1-96 now */
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
/*
* For SHA1-96, the authcode will be the last 12 bytes in the packet
*/
bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE);
lanplus_HMAC(session->v2_data.integrity_alg,
session->v2_data.k1,
20,
rs->data + IMPI_LANPLUS_OFFSET_AUTHTYPE,
rs->data_len - IMPI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
generated_authcode,
&generated_authcode_length);
if (verbose > 3)
{
printf("Validating authcode\n");
printbuf(session->v2_data.k1, 20, "K1");
printbuf(rs->data + IMPI_LANPLUS_OFFSET_AUTHTYPE,
rs->data_len - IMPI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
"Authcode Input Data");
printbuf(generated_authcode, 12, "Generated authcode");
printbuf(bmc_authcode, 12, "Expected authcode");
}
assert(generated_authcode_length == 20);
return (memcmp(bmc_authcode, generated_authcode, 12) == 0);
}
/*
* lanplus_decrypt_payload
*
*
* param input points to the beginning of the payload (which will be the IV if
* we are using AES)
* param payload_size [out] will be set to the size of the payload EXCLUDING
* padding
*
* returns 0 on success (we were able to successfully decrypt the packet)
* 1 on failure (we were unable to successfully decrypt the packet)
*/
int lanplus_decrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * payload_size)
{
unsigned char * decrypted_payload;
unsigned int bytes_decrypted;
if (crypt_alg == IPMI_CRYPT_NONE)
{
/* We are not encrypted. The paylaod size is is everything. */
*payload_size = input_length;
memmove(output, input, input_length);
return 0;
}
/* We only support AES */
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
decrypted_payload = (unsigned char*)malloc(input_length);
lanplus_decrypt_aes_cbc_128(input, /* IV */
key, /* Key */
input +
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Data to decrypt */
input_length -
IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Input length */
decrypted_payload, /* output */
&bytes_decrypted); /* bytes written */
if (bytes_decrypted != 0)
{
/* Success */
unsigned char conf_pad_length;
int i;
memmove(output,
decrypted_payload,
bytes_decrypted);
/*
* We have to determine the payload size, by substracting the padding, etc.
* The last byte of the decrypted payload is the confidentiality pad length.
*/
conf_pad_length = decrypted_payload[bytes_decrypted - 1];
*payload_size = bytes_decrypted - conf_pad_length - 1;
/*
* Extra test to make sure that the padding looks like it should (should start
* with 0x01, 0x02, 0x03, etc...
*/
for (i = 0; i < conf_pad_length; ++i)
{
if (decrypted_payload[*payload_size + i] == i)
{
printf("ERROR: Malformed payload padding\n");
assert(0);
}
}
}
else
{
printf("ERROR: lanplus_decrypt_aes_cbc_128 decryptd 0 bytes\n");
assert(0);
}
free(decrypted_payload);
return (bytes_decrypted == 0);
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_CRYPT_H
#define IPMI_LANPLUS_CRYPT_H
#include <ipmitool/ipmi_intf.h>
/*
* See the implementation file for documentation
*/
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const unsigned char * hmac);
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const unsigned char * hmac);
int lanplus_generate_rakp3_authcode(char * buffer,
const struct ipmi_session * session,
unsigned int * auth_length);
int lanplus_generate_sik(struct ipmi_session * session);
int lanplus_generate_k1(struct ipmi_session * session);
int lanplus_generate_k2(struct ipmi_session * session);
int lanplus_encrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * bytesWritten);
int lanplus_decrypt_payload(unsigned char crypt_alg,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned short * payload_size);
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
struct ipmi_session * session);
#endif /* IPMI_LANPLUS_CRYPT_H */

View File

@ -0,0 +1,296 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include "lanplus.h"
#include "lanplus_crypt_impl.h"
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <assert.h>
/*
* lanplus_seed_prng
*
* Seed our PRNG with the specified number of bytes from /dev/random
*
* param bytes specifies the number of bytes to read from /dev/random
*
* returns 0 on success
* 1 on failure
*/
int lanplus_seed_prng(unsigned int bytes)
{
if (! RAND_load_file("/dev/urandom", bytes))
return 1;
else
return 0;
}
/*
* lanplus_rand
*
* Generate a random number of the specified size
*
* param num_bytes [in] is the size of the random number to be
* generated
* param buffer [out] is where we will place our random number
*
* return 0 on success
* 1 on failure
*/
int
lanplus_rand(unsigned char * buffer, unsigned int num_bytes)
{
#define IPMI_LANPLUS_FAKE_RAND 1
#ifdef IPMI_LANPLUS_FAKE_RAND
/*
* This code exists so that we can easily find the generated random number
* in the hex dumps.
*/
int i;
for (i = 0; i < num_bytes; ++i)
buffer[i] = 0x70 | i;
return 0;
#else
return (! RAND_bytes(buffer, num_bytes));
#endif
}
/*
* lanplus_HMAC
*
* param mac specifies the algorithm to be used, currently only SHA1 is supported
* param key is the key used for HMAC generation
* param key_len is the lenght of key
* param d is the data to be MAC'd
* param n is the length of the data at d
* param md is the result of the HMAC algorithm
* param md_len is the length of md
*
* returns a pointer to md
*/
unsigned char *
lanplus_HMAC(unsigned char mac,
const void *key,
int key_len,
const unsigned char *d,
int n,
unsigned char *md,
unsigned int *md_len)
{
const EVP_MD *evp_md;
if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
(mac == IPMI_INTEGRITY_HMAC_SHA1_96))
evp_md = EVP_sha1();
else
{
printf("Invalid mac type 0x%x in lanplus_HMAC\n", mac);
assert(0);
}
return HMAC(evp_md, key, key_len, d, n, md, md_len);
}
/*
* lanplus_encrypt_aes_cbc_128
*
* Encrypt with the AES CBC 128 algorithm
*
* param iv is the 16 byte initialization vector
* param key is the 16 byte key used by the AES algorithm
* param input is the data to be encrypted
* param input_length is the number of bytes to be encrypted. This MUST
* be a multiple of the block size, 16.
* param output is the encrypted output
* param bytes_written is the number of bytes written. This param is set
* to 0 on failure, or if 0 bytes were input.
*/
void
lanplus_encrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written)
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
*bytes_written = 0;
if (input_length == 0)
return;
if (verbose > 2)
{
printbuf(iv, 16, "encrypting with this IV");
printbuf(key, 16, "encrypting with this key");
printbuf(input, input_length, "encrypting this data");
}
/*
* The default implementation adds a whole block of padding if the input
* data is perfectly aligned. We would like to keep that from happening.
* We have made a point to have our input perfectly padded.
*/
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
if(!EVP_EncryptUpdate(&ctx, output, bytes_written, input, input_length))
{
/* Error */
*bytes_written = 0;
return;
}
else
{
unsigned int tmplen;
if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, &tmplen))
{
*bytes_written = 0;
return; /* Error */
}
else
{
/* Success */
*bytes_written += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
}
}
}
/*
* lanplus_decrypt_aes_cbc_128
*
* Decrypt with the AES CBC 128 algorithm
*
* param iv is the 16 byte initialization vector
* param key is the 16 byte key used by the AES algorithm
* param input is the data to be decrypted
* param input_length is the number of bytes to be decrypted. This MUST
* be a multiple of the block size, 16.
* param output is the decrypted output
* param bytes_written is the number of bytes written. This param is set
* to 0 on failure, or if 0 bytes were input.
*/
void
lanplus_decrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written)
{
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (verbose > 2)
{
printbuf(iv, 16, "decrypting with this IV");
printbuf(key, 16, "decrypting with this key");
printbuf(input, input_length, "decrypting this data");
}
*bytes_written = 0;
if (input_length == 0)
return;
/*
* The default implementation adds a whole block of padding if the input
* data is perfectly aligned. We would like to keep that from happening.
* We have made a point to have our input perfectly padded.
*/
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
if(!EVP_DecryptUpdate(&ctx, output, bytes_written, input, input_length))
{
/* Error */
printf("ERROR: decrypt update failed\n");
*bytes_written = 0;
return;
}
else
{
unsigned int tmplen;
if(!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, &tmplen))
{
char buffer[1000];
ERR_error_string(ERR_get_error(), buffer);
printf("the ERR error %s\n", buffer);
printf("ERROR: decrypt final failed\n");
*bytes_written = 0;
return; /* Error */
}
else
{
/* Success */
*bytes_written += tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
}
}
if (verbose > 1)
{
printf("Decrypted %d encrypted bytes\n", input_length);
printbuf(output, *bytes_written, "Decrypted this data");
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_CRYPT_IMPL_H
#define IPMI_LANPLUS_CRYPT_IMPL_H
int
lanplus_seed_prng(unsigned int bytes);
int
lanplus_rand(unsigned char * buffer, unsigned int num_bytes);
unsigned char *
lanplus_HMAC(unsigned char mac, const void *key, int key_len,
const unsigned char *d, int n, unsigned char *md,
unsigned int *md_len);
void
lanplus_encrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written);
void
lanplus_decrypt_aes_cbc_128(const unsigned char * iv,
const unsigned char * key,
const unsigned char * input,
unsigned int input_length,
unsigned char * output,
unsigned int * bytes_written);
#endif /* IPMI_LANPLUS_CRYPT_IMPL_H */

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include "lanplus.h"
#include "lanplus_dump.h"
extern const struct valstr ipmi_rakp_return_codes[];
extern const struct valstr ipmi_priv_levels[];
extern const struct valstr ipmi_auth_algorithms[];
extern const struct valstr ipmi_integrity_algorithms[];
extern const struct valstr ipmi_encryption_algorithms[];
#define DUMP_PREFIX_INCOMING "<< "
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp)
{
printf("%sOPEN SESSION RESPONSE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.open_session_response.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Maximum privilege level : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.max_priv_level,
ipmi_priv_levels));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
(long)rsp->payload.open_session_response.console_id);
printf("%s BMC Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
(long)rsp->payload.open_session_response.bmc_id);
printf("%s Negotiated authenticatin algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.auth_alg,
ipmi_auth_algorithms));
printf("%s Negotiated integrity algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.integrity_alg,
ipmi_integrity_algorithms));
printf("%s Negotiated encryption algorithm : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.open_session_response.crypt_alg,
ipmi_encryption_algorithms));
printf("\n");
}
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, unsigned char auth_alg)
{
int i;
printf("%sRAKP 2 MESSAGE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.rakp2_message.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
(long)rsp->payload.rakp2_message.console_id);
printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
printf("\n");
printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
printf("\n");
switch(auth_alg)
{
case IPMI_AUTH_RAKP_NONE:
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
break;
case IPMI_AUTH_RAKP_HMAC_SHA1:
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 20; ++i)
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
printf("\n");
break;
case IPMI_AUTH_RAKP_HMAC_MD5:
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
printf("\n");
break;
default:
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
}
printf("\n");
}
void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, unsigned char auth_alg)
{
int i;
printf("%sRAKP 4 MESSAGE\n", DUMP_PREFIX_INCOMING);
printf("%s Message tag : 0x%02x\n",
DUMP_PREFIX_INCOMING,
rsp->payload.rakp2_message.message_tag);
printf("%s RMCP+ status : %s\n",
DUMP_PREFIX_INCOMING,
val2str(rsp->payload.rakp2_message.rakp_return_code,
ipmi_rakp_return_codes));
printf("%s Console Session ID : 0x%08lx\n",
DUMP_PREFIX_INCOMING,
(long)rsp->payload.rakp2_message.console_id);
printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
printf("\n");
printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 16; ++i)
printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
printf("\n");
switch(auth_alg)
{
case IPMI_AUTH_RAKP_NONE:
printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
break;
case IPMI_AUTH_RAKP_HMAC_SHA1:
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 12; ++i)
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
printf("\n");
break;
case IPMI_AUTH_RAKP_HMAC_MD5:
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
for (i = 0; i < 12; ++i)
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
printf("\n");
break;
default:
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
}
printf("\n");
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LANPLUS_DUMP_H
#define IPMI_LANPLUS_DUMP_H
#include <ipmitool/ipmi_intf.h>
/* See the implementation file for documentation */
void lanplus_dump_open_session_response(const struct ipmi_rs * rsp);
void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, unsigned char auth_alg);
void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, unsigned char auth_alg);
#endif /* IPMI_LANPLUS_DUMP_H */

View File

@ -0,0 +1,60 @@
#include "lanplus.h"
const struct valstr ipmi_rakp_return_codes[] = {
{ IPMI_RAKP_STATUS_NO_ERRORS, "no errors" },
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION, "insufficient resources for session" },
{ IPMI_RAKP_STATUS_INVALID_SESSION_ID, "invalid session ID" },
{ IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE, "invalid payload type" },
{ IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM, "invalid authentication algorithm" },
{ IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM, "invalid integrity algorithm" },
{ IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD, "no matching authentication algorithm"},
{ IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD, "no matching integrity payload" },
{ IPMI_RAKP_STATUS_INACTIVE_SESSION_ID, "inactive session ID" },
{ IPMI_RAKP_STATUS_INVALID_ROLE, "invalid role" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED, "unauthorized role requested" },
{ IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE, "insufficient resources for role" },
{ IPMI_RAKP_STATUS_INVALID_NAME_LENGTH, "invalid name length" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_NAME, "unauthorized name" },
{ IPMI_RAKP_STATUS_UNAUTHORIZED_GUID, "unauthorized GUID" },
{ IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE, "invlalid integrity check value" },
{ IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM, "invalid confidentiality algorithm" },
{ IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH, "no matching cipher suite" },
{ IPMI_RAKP_STATUS_ILLEGAL_PARAMTER, "illegal parameter" },
{ 0, 0 },
};
const struct valstr ipmi_priv_levels[] = {
{ IPMI_PRIV_CALLBACK, "callback" },
{ IPMI_PRIV_USER, "user" },
{ IPMI_PRIV_OPERATOR, "operator" },
{ IPMI_PRIV_ADMIN, "admin" },
{ IPMI_PRIV_OEM, "oem" },
{ 0, 0 },
};
const struct valstr ipmi_auth_algorithms[] = {
{ IPMI_AUTH_RAKP_NONE, "none" },
{ IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" },
{ IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" },
{ 0, 0 },
};
const struct valstr ipmi_integrity_algorithms[] = {
{ IPMI_INTEGRITY_NONE, "none" },
{ IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" },
{ IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" },
{ IPMI_INTEGRITY_MD5_128 , "md5_128" },
{ 0, 0 },
};
const struct valstr ipmi_encryption_algorithms[] = {
{ IPMI_CRYPT_NONE, "none" },
{ IPMI_CRYPT_AES_CBC_128, "aes_cbc_128" },
{ IPMI_CRYPT_XRC4_128, "xrc4_128" },
{ IPMI_CRYPT_XRC4_40, "xrc4_40" },
{ 0, 0 },
};

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_RMCP_H
#define IPMI_RMCP_H
#include <ipmitool/helper.h>
#include "lanplus.h"
#define RMCP_VERSION_1 0x06
#define RMCP_UDP_PORT 0x26f /* port 623 */
#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
#define RMCP_TYPE_MASK 0x80
#define RMCP_TYPE_NORM 0x00
#define RMCP_TYPE_ACK 0x01
static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
{ RMCP_TYPE_NORM, "Normal RMCP" },
{ RMCP_TYPE_ACK, "RMCP ACK" },
{ 0, NULL }
};
#define RMCP_CLASS_MASK 0x1f
#define RMCP_CLASS_ASF 0x06
#define RMCP_CLASS_IPMI 0x07
#define RMCP_CLASS_OEM 0x08
static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
{ RMCP_CLASS_ASF, "ASF" },
{ RMCP_CLASS_IPMI, "IPMI" },
{ RMCP_CLASS_OEM, "OEM" },
{ 0, NULL }
};
/* RMCP message header */
struct rmcp_hdr {
unsigned char ver;
unsigned char __reserved;
unsigned char seq;
unsigned char class;
} __attribute__((packed));
int handle_rmcp(struct ipmi_intf * intf, unsigned char * data, int data_len);
#endif /* IPMI_RMCP_H */

View File

@ -0,0 +1,43 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#
# You acknowledge that this software is not designed or intended for use
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_lipmi.la
noinst_LTLIBRARIES = @INTF_LIPMI_LIB@
libintf_lipmi_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_lipmi_la_SOURCES = lipmi.c

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stropts.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <sys/lipmi/lipmi_intf.h>
#define IPMI_LIPMI_DEV "/dev/lipmi"
extern int verbose;
static int ipmi_lipmi_open(struct ipmi_intf * intf)
{
intf->fd = open(IPMI_LIPMI_DEV, O_RDWR);
if (intf->fd < 0) {
perror("Could not open lipmi device");
return -1;
}
intf->opened = 1;
return intf->fd;
}
static void ipmi_lipmi_close(struct ipmi_intf * intf)
{
if (intf && intf->fd >= 0)
close(intf->fd);
intf->fd = -1;
intf->opened = 0;
}
static struct ipmi_rs * ipmi_lipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
{
struct strioctl istr;
static struct lipmi_reqrsp reqrsp;
static struct ipmi_rs rsp;
static int curr_seq = 0;
if (!intf || !req)
return NULL;
if (!intf->opened && intf->open && intf->open(intf) < 0)
return NULL;
memset(&reqrsp, 0, sizeof(reqrsp));
reqrsp.req.fn = req->msg.netfn;
reqrsp.req.lun = 0;
reqrsp.req.cmd = req->msg.cmd;
reqrsp.req.datalength = req->msg.data_len;
memcpy(reqrsp.req.data, req->msg.data, req->msg.data_len);
reqrsp.rsp.datalength = RECV_MAX_PAYLOAD_SIZE;
istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
istr.ic_timout = 0;
istr.ic_dp = (char *)&reqrsp;
istr.ic_len = sizeof(struct lipmi_reqrsp);
if (verbose > 1) {
printf("LIPMI req.fn : %x\n", reqrsp.req.fn);
printf("LIPMI req.lun : %x\n", reqrsp.req.lun);
printf("LIPMI req.cmd : %x\n", reqrsp.req.cmd);
printf("LIPMI req.datalength : %d\n", reqrsp.req.datalength);
}
if (ioctl(intf->fd, I_STR, &istr) < 0) {
perror("LIPMI IOCTL: I_STR");
return NULL;
}
memset(&rsp, 0, sizeof(struct ipmi_rs));
rsp.ccode = reqrsp.rsp.ccode;
rsp.data_len = reqrsp.rsp.datalength;
if (!rsp.ccode && rsp.data_len)
memcpy(rsp.data, reqrsp.rsp.data, rsp.data_len);
return &rsp;
}
struct ipmi_intf ipmi_lipmi_intf = {
name: "lipmi",
desc: "Solaris x86 LIPMI Interface",
open: ipmi_lipmi_open,
close: ipmi_lipmi_close,
sendrecv: ipmi_lipmi_send_cmd,
target_addr: IPMI_BMC_SLAVE_ADDR,
};

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
#ifndef IPMI_LIPMI_H
#define IPMI_LIPMI_H
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#define LIPMI_DEV "/dev/lipmi"
struct ipmi_rs * ipmi_lipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
int ipmi_lipmi_open(struct ipmi_intf * intf);
void ipmi_lipmi_close(struct ipmi_intf * intf);
int lipmi_intf_setup(struct ipmi_intf ** intf);
#endif

View File

@ -32,16 +32,12 @@
# in the design, construction, operation or maintenance of any nuclear
# facility.
MAINTAINERCLEANFILES = Makefile.in
MAINTAINERCLEANFILES = Makefile.in
plugindir = $(pluginpath)
INCLUDES = -I$(top_srcdir)/include
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_open.la
plugin_LTLIBRARIES = @PLUGIN_INTF_OPEN@
noinst_LTLIBRARIES = @STATIC_INTF_OPEN@
libintf_open_la_LDFLAGS = @LDFLAGS_INTF_OPEN@
libintf_open_la_LIBADD = $(top_srcdir)/lib/libipmitool.la
noinst_LTLIBRARIES = @INTF_OPEN_LIB@
libintf_open_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_open_la_SOURCES = open.c open.h

View File

@ -45,95 +45,128 @@
#include <sys/stat.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <linux/ipmi.h>
#include <config.h>
#include "open.h"
#ifdef HAVE_OPENIPMI_H
# include <linux/ipmi.h>
#else
# include "open.h"
#endif
static int curr_seq;
extern int verbose;
struct ipmi_session lan_session;
struct ipmi_intf ipmi_openipmi_intf = {
.open = ipmi_openipmi_open,
.close = ipmi_openipmi_close,
.sendrecv = ipmi_openipmi_send_cmd,
};
#define IPMI_OPENIPMI_DEV "/dev/ipmi0"
void ipmi_openipmi_close(struct ipmi_intf * intf)
{
if (intf && intf->fd >= 0)
close(intf->fd);
}
int ipmi_openipmi_open(struct ipmi_intf * intf, char * dev, int __unused1, char * __unused2, char * __unused3)
static int ipmi_openipmi_open(struct ipmi_intf * intf)
{
int i = 0;
if (!dev)
intf->fd = open(OPENIPMI_DEV, O_RDWR);
else
intf->fd = open(dev, O_RDWR);
intf->fd = open(IPMI_OPENIPMI_DEV, O_RDWR);
if (intf->fd < 0) {
perror("Could not open ipmi device");
lperror(LOG_ERR, "Could not open ipmi device");
return -1;
}
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) {
perror("Could not set to get events");
lperror(LOG_ERR, "Could not set to get events");
return -1;
}
curr_seq = 0;
if (intf->my_addr) {
unsigned int a = intf->my_addr;
if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a)) {
lperror(LOG_ERR, "Could not set IPMB address");
return -1;
}
lprintf(LOG_DEBUG, "Set my IPMB address to 0x%x", intf->my_addr);
}
intf->opened = 1;
return intf->fd;
}
struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
static void ipmi_openipmi_close(struct ipmi_intf * intf)
{
if (intf && intf->fd >= 0)
close(intf->fd);
intf->opened = 0;
}
static struct ipmi_rs *ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
{
struct ipmi_recv recv;
struct ipmi_addr addr;
struct ipmi_system_interface_addr bmc_addr;
struct ipmi_system_interface_addr bmc_addr = {
addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
channel: IPMI_BMC_CHANNEL,
};
struct ipmi_ipmb_addr ipmb_addr = {
addr_type: IPMI_IPMB_ADDR_TYPE,
};
struct ipmi_req _req;
static struct ipmi_rs rsp;
static int curr_seq = 0;
fd_set rset;
if (!req)
if (!intf || !req)
return NULL;
if (!intf->opened && intf->open && intf->open(intf) < 0)
return NULL;
if (verbose > 2)
printbuf(req->msg.data, req->msg.data_len, "send_cmd");
/*
* setup and send message
*/
memset(&_req, 0, sizeof(struct ipmi_req));
if (verbose > 2)
printbuf(req->msg.data, req->msg.data_len, "send_ipmi_cmd_dev");
if (intf->target_addr &&
intf->target_addr != intf->my_addr) {
/* use IPMB address if needed */
ipmb_addr.slave_addr = intf->target_addr;
_req.addr = (char *) &ipmb_addr;
_req.addr_len = sizeof(ipmb_addr);
lprintf(LOG_DEBUG, "Sending request to IPMB target @ 0x%x",
intf->target_addr);
} else {
/* otherwise use system interface */
lprintf(LOG_DEBUG+2, "Sending request to System Interface");
_req.addr = (char *) &bmc_addr;
_req.addr_len = sizeof(bmc_addr);
}
FD_ZERO(&rset);
FD_SET(intf->fd, &rset);
bmc_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
bmc_addr.channel = IPMI_BMC_CHANNEL;
bmc_addr.lun = 0;
_req.addr = (char *) &bmc_addr;
_req.addr_len = sizeof(bmc_addr);
_req.msgid = curr_seq++;
_req.msg.netfn = req->msg.netfn;
_req.msg.cmd = req->msg.cmd;
_req.msg.data = req->msg.data;
_req.msg.data_len = req->msg.data_len;
if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
printf("Error sending command: %s\n", strerror(errno));
lperror(LOG_ERR, "Error sending command");
return NULL;
}
/*
* wait for and retrieve response
*/
FD_ZERO(&rset);
FD_SET(intf->fd, &rset);
if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
perror("select");
lperror(LOG_ERR, "Error doing select");
return NULL;
}
if (!FD_ISSET(intf->fd, &rset)) {
printf("Error no data available\n");
lprintf(LOG_ERR, "Error no data available");
return NULL;
}
@ -144,28 +177,30 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq
/* get data */
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
printf("Error receiving message: %s\n", strerror(errno));
lperror(LOG_ERR, "Error receiving message");
if (errno != EMSGSIZE)
return NULL;
}
if (verbose > 1) {
printf("Got message:\n");
printf(" type = %d\n", recv.recv_type);
printf(" channel = 0x%x\n", addr.channel);
printf(" msgid = %ld\n", recv.msgid);
printf(" netfn = 0x%x\n", recv.msg.netfn);
printf(" cmd = 0x%x\n", recv.msg.cmd);
if (verbose > 4) {
fprintf(stderr, "Got message:");
fprintf(stderr, " type = %d\n", recv.recv_type);
fprintf(stderr, " channel = 0x%x\n", addr.channel);
fprintf(stderr, " msgid = %ld\n", recv.msgid);
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
if (recv.msg.data && recv.msg.data_len) {
printf(" data_len = %d\n", recv.msg.data_len);
printf(" data =");
printbuf(recv.msg.data, recv.msg.data_len, "data");
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
fprintf(stderr, " data = %s\n",
buf2str(recv.msg.data, recv.msg.data_len));
}
}
/* save completion code */
rsp.ccode = recv.msg.data[0];
rsp.data_len = recv.msg.data_len - 1;
/* save response data for caller */
if (!rsp.ccode && rsp.data_len) {
memmove(rsp.data, rsp.data + 1, rsp.data_len);
rsp.data[recv.msg.data_len] = 0;
@ -174,10 +209,12 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq
return &rsp;
}
int open_intf_setup(struct ipmi_intf ** intf)
{
*intf = &ipmi_openipmi_intf;
return 0;
}
struct ipmi_intf ipmi_open_intf = {
name: "open",
desc: "Linux OpenIPMI Interface",
open: ipmi_openipmi_open,
close: ipmi_openipmi_close,
sendrecv: ipmi_openipmi_send_cmd,
target_addr: IPMI_BMC_SLAVE_ADDR,
};
int intf_setup(struct ipmi_intf ** intf) __attribute__ ((weak, alias("open_intf_setup")));

Some files were not shown because too many files have changed in this diff Show More