ipmi 0.1.2

IPMI v2.0 RMCP+ client library (async-first + optional blocking) with session authentication, integrity and confidentiality.
Documentation

ipmi

A production-oriented IPMI v2.0 RMCP+ client library (async-first + optional blocking).

This crate focuses on:

  • IPMI v2.0 RMCP+ session establishment (Open Session + RAKP 1-4)
  • Integrity: HMAC-SHA1-96
  • Confidentiality: AES-CBC-128
  • Async API (tokio, default)
  • Blocking API (feature blocking)

Note: IPMI is a large specification. This crate implements a secure and commonly supported baseline (mandatory-to-implement algorithms) and provides a solid foundation for adding more commands and cipher suites.

Install

Async API (default):

[dependencies]
ipmi = "0.1"

Blocking API without pulling tokio:

[dependencies]
ipmi = { version = "0.1", default-features = false, features = ["blocking"] }

Observability (optional):

[dependencies]
ipmi = { version = "0.1", features = ["tracing", "metrics"] }

Quick start (async)

use ipmi::{Client, PrivilegeLevel};

// You need a tokio runtime in your application to use the async client.
#[tokio::main]
async fn main() -> ipmi::Result<()> {
    let target = "192.0.2.10:623".parse()?;

    let client = Client::builder(target)
        .username("ADMIN")
        .password("secret")
        .privilege_level(PrivilegeLevel::Administrator)
        .timeout(std::time::Duration::from_secs(2))
        .retries(3)
        .build()
        .await?;

    let device_id = client.get_device_id().await?;
    println!("BMC: {:?}", device_id);

    // Optional: explicitly close the session when you're done.
    let _ = client.close_session().await;

    Ok(())
}

Quick start (blocking)

use ipmi::{BlockingClient, PrivilegeLevel};

fn main() -> ipmi::Result<()> {
    let target = "192.0.2.10:623".parse()?;

    let client = BlockingClient::builder(target)
        .username("ADMIN")
        .password("secret")
        .privilege_level(PrivilegeLevel::Administrator)
        .timeout(std::time::Duration::from_secs(2))
        .retries(3)
        .build()?;

    let device_id = client.get_device_id()?;
    println!("BMC: {:?}", device_id);

    // Optional: explicitly close the session when you're done.
    let _ = client.close_session();

    Ok(())
}

Typed commands

The crate exposes a typed command interface in ipmi::commands. You can execute built-in commands directly, or implement commands::Command for custom commands:

use ipmi::commands::GetDeviceId;

let device_id = client.execute(GetDeviceId).await?;
let device_id = blocking_client.execute(GetDeviceId)?;

Security notes

  • Password / KG are stored in memory only for the duration of session establishment and are zeroized on drop.
  • Session keys are zeroized when the client is dropped.
  • The client verifies integrity checks (HMAC) before decrypting payloads.
  • The library avoids unwrap()/expect() in production code.

Feature support

  • Transport: UDP/623 (LAN)
  • Session: RMCP+ / RAKP (IPMI v2.0)
  • Commands:
    • Get Device ID (netfn 0x06, cmd 0x01)
    • Get Self Test Results (netfn 0x06, cmd 0x04)
    • Get System GUID (netfn 0x06, cmd 0x37)
    • Get Chassis Status (netfn 0x00, cmd 0x01)
    • Chassis Control (netfn 0x00, cmd 0x02)
    • Get Channel Authentication Capabilities (netfn 0x06, cmd 0x38)
    • Close Session (netfn 0x06, cmd 0x3C)
    • send_raw() for arbitrary commands