iscsi-client-rs
A pure‑Rust iSCSI initiator library (with example CLI) for interacting with iSCSI targets over TCP. Build/parse PDUs, perform login (plain or CHAP), and exchange SCSI commands asynchronously.
⚠️ Status: tested against Linux
tgtonly. Other targets may behave differently. Use with care.
Features
- iSCSI Login across Security → Operational → Full‑Feature phases
- CHAP (MD5) authentication (challenge parsing + response building)
- Plain login (no authentication)
- Async networking via Tokio
- High‑level state machines for:
- Login (plain & CHAP)
- NOP (Nop-Out / Nop-In)
- SCSI READ(10) (Data-In)
- SCSI WRITE(10) (Data-Out; ImmediateData path)
- Zero C dependencies
Quick start
Install
# Cargo.toml
[]
= "*"
Connect + login (state machine)
use ;
use ;
async
Architecture overview
Connection & PDU framing
Connection wraps a Tokio TCP stream and frames iSCSI PDUs by their 48‑byte BHS. It:
- writes PDUs via
ToBytes - reads headers + payload with a timeout
- coalesces multi‑segment payloads using
Continue/Finalbits - completes a pending request by Initiator Task Tag (ITT) and delivers a fully reconstructed
PDUWithData<T>to the caller
Sequence & task numbers
- ITT (Initiator Task Tag): request correlation per command/flow
- CmdSN / ExpStatSN: maintained by caller; on responses we bump
ExpStatSN = stat_sn + 1
Utility builders produce PDUs with correct fields; state machines update counters for you at the right moments.
Login state machine
Two branches share a common context LoginCtx and output LoginStatus.
-
Plain: single step —
Operational → FullFeature+ login keys -
CHAP: four steps
Security → Security— advertise security keys (noCHAP_A)Security → Security— sendCHAP_A=5Security → Operational (Transit)— computeCHAP_RfromCHAP_I/CHAP_C, sendCHAP_N/CHAP_ROperational → FullFeature (Transit)— send operational keys
APIs:
// Pick a branch and run until Done
;
;
pub async ;
CHAP details
- Parses challenge text for
CHAP_IandCHAP_C(accepts0x…or raw hex) - Computes
CHAP_R = MD5( one-octet CHAP_I || secret || challenge )as uppercase hex with0xprefix
NOP state machine
Ping the target and verify ExpStatSN handling.
use ;
let lun = ;
let ttt = DEFAULT_TAG;
let mut nctx = new;
// one round trip
let _st = run_nop.await?;
SCSI commands
READ(10) state machine (Data‑In)
ReadStart— sendsSCSI READ(10)(16‑byte padded CDB) and records countersReadWait— drains allScsiDataInfragments, appends data, updatesExpStatSNon the fragment that carriesstat_sn, and returns the assembled buffer
use ;
use ;
let mut cdb = ;
build_read10;
let mut rctx = ReadCtx ;
let rr = run_read.await?;
println!;
WRITE(10) state machine (Data‑Out)
Two paths:
- ImmediateData (supported): if negotiated
ImmediateData=Yesand payload ≤FirstBurstLength, data is embedded into theScsiCommandRequestand sent in one go; we then wait forScsiCommandResponseand validateResponseCode/Status. - R2T (WIP): if
ImmediateData=Noor payload is larger, the target may issue R2T. Full Data‑Out sequencing (respectingMaxBurstLengthandMaxRecvDataSegmentLength) is on the roadmap. Currently returns an error:R2T not implemented.
use build_write10;
use ;
let mut cdb = ;
build_write10;
let mut wctx = WriteCtx ;
let ws = run_write.await?;
println!;
Testing
Fixture‑driven tests validate parsing and key ordering without mocks.
Current status (integration): Right now we test by running the real client against a real target in Docker (typically tgt) and executing the main entrypoint. This gives us end-to-end coverage over TCP and exercises login (Plain/CHAP), NOP, and SCSI READ/WRITE.
Typical flow: *1. Start a local iSCSI target in Docker (e.g., tgt) with a simple LUN and, if desired, CHAP enabled. *2. Run the client with your test config (plain or CHAP) and observe PDUs / traces.
Run unit tests:
Run inegrational tests:
CLI
An example CLI demonstrates discovery/login and simple I/O using the same library APIs. See examples/ (if enabled in this version).
Roadmap
Protocol & features * Header/Data digests (CRC32C) with optional NIC offload * Multi-connection sessions (MC/S), connection reinstatement, session recovery * Error Recovery Levels (ERL1/ERL2): SNACKs, data retransmit, CmdSN/StatSN windowing * Mutual CHAP (bi-directional auth), CHAP key normalization & strict parsing * Discovery: SendTargets (Text) and basic iSNS client * Task Management: ABORT TASK, LOGICAL UNIT RESET, CLEAR TASK SET, etc. * Common SCSI ops: REPORT LUNS, INQUIRY VPD, MODE SENSE/SELECT, UNMAP, WRITE SAME, COMPARE-AND-WRITE * Asynchronous Event Notification (AEN) / Unit Attention flow * IPv6, jumbo frames; optional TLS/TCP (where supported by targets)
Performance * Zero-copy buffers for PDU build/parse, fewer allocations * Pipelining / outstanding command windows, auto-tuning of MaxBurstLength, FirstBurstLength, ImmediateData * Scatter-gather for large Data-Out * Benchmarks suite (throughput, latency) with reproducible network profiles
API & ergonomics * Unified state_machine API for Login, NOP, READ/WRITE, TMFs (cancel/timeout/cancellation tokens) * Pluggable allocators/ITT strategies, wrap-around handling * Structured errors with retry hints; back-pressure & graceful shutdown
Testing & CI * Matrix with multiple targets (tgt, LIO/targetcli, SCST, FreeBSD ctld) * Deterministic packet capture & byte-for-byte fixtures for every login hop * Fuzzing (cargo-fuzz/proptest) for PDUs and text-key parsing * Long-haul stability tests (hours-long READ/WRITE with keepalives)
Docs & examples * End-to-end examples: plain login, CHAP, READ/WRITE, TMFs * Migration guide, troubleshooting (Auth failures, digests, ERL) * RFC alignment notes (7143/7144/SPC/SAM) and conformance checklist
Contributing
Issues and PRs are welcome. Please run:
License
Licensed under either of
- Apache License, Version 2.0
- MIT license
at your option.
Acknowledgments
Thanks to the iSCSI community and Linux tgt for a solid reference target to test against.