Skip to main content

tokio_nbd/
errors.rs

1//! Error types for the NBD (Network Block Device) protocol.
2//!
3//! This module defines the error types used in the NBD protocol implementation:
4//!
5//! - [`ProtocolError`]: Errors that can occur during the normal NBD transmission loop
6//! - [`OptionReplyError`]: Errors that can occur during the option negotiation phase
7//!
8//! These error types correspond to the error codes defined in the NBD protocol
9//! specification, with appropriate Rust representation.
10//!
11//! # Examples
12//!
13//! ```
14//! use tokio_nbd::errors::ProtocolError;
15//!
16//! // Check if an error is a specific type
17//! fn handle_error(error: ProtocolError) {
18//!     if error == ProtocolError::CommandNotSupported {
19//!         println!("The command is not supported by this server");
20//!     } else if error == ProtocolError::NoSpaceLeft {
21//!         println!("The operation failed because the device is full");
22//!     }
23//! }
24//! ```
25
26use int_enum::IntEnum;
27use thiserror::Error;
28
29/// Errors that can occur during the normal NBD transmission loop.
30///
31/// These errors correspond to the standard NBD error codes defined in the protocol
32/// specification. Each error maps to a specific numeric value that is sent over
33/// the wire to the client.
34///
35/// The error codes follow POSIX errno values where possible, as per the NBD protocol
36/// specification.
37#[repr(u32)]
38#[derive(Debug, Error, IntEnum, PartialEq, Eq)]
39pub enum ProtocolError {
40    /// The client is not permitted to perform the requested operation.
41    ///
42    /// Corresponds to POSIX EPERM (1) and NBD_EPERM.
43    #[error("Command not permitted (NBD_EPERM)")]
44    CommandNotPermitted = 1,
45
46    /// An input/output error occurred during the operation.
47    ///
48    /// Corresponds to POSIX EIO (5) and NBD_EIO.
49    #[error("Input/output error (NBD_EIO)")]
50    IO = 5,
51
52    /// The server cannot allocate sufficient memory to complete the operation.
53    ///
54    /// Corresponds to POSIX ENOMEM (12) and NBD_ENOMEM.
55    #[error("Cannot allocate memory (NBD_ENOMEM)")]
56    OutOfMemory = 12,
57
58    /// The client provided an invalid argument or request structure.
59    ///
60    /// Corresponds to POSIX EINVAL (22) and NBD_EINVAL.
61    #[error("Invalid argument (NBD_EINVAL)")]
62    InvalidArgument = 22,
63
64    /// There is no space left on the storage device to complete the operation.
65    ///
66    /// Corresponds to POSIX ENOSPC (28) and NBD_ENOSPC.
67    #[error("No space left on device (NBD_ENOSPC)")]
68    NoSpaceLeft = 28,
69
70    /// The requested operation would cause a value to overflow.
71    ///
72    /// Corresponds to POSIX EOVERFLOW (75) and NBD_EOVERFLOW.
73    #[error("Value too large (NBD_EOVERFLOW)")]
74    ValueTooLarge = 75,
75
76    /// The requested command is not supported by the server implementation.
77    ///
78    /// Corresponds to POSIX ENOTSUP (95) and NBD_ENOTSUP.
79    #[error("Command not supported (NBD_ENOTSUP)")]
80    CommandNotSupported = 95,
81
82    /// The server is in the process of shutting down and cannot process the request.
83    ///
84    /// Corresponds to POSIX ESHUTDOWN (108) and NBD_ESHUTDOWN.
85    #[error("Server is in the process of being shut down (NBD_ESHUTDOWN)")]
86    ServerShuttingDown = 108,
87}
88
89/// Errors that can occur during the option negotiation phase of the NBD protocol.
90///
91/// These errors are sent in reply to option requests from the client during the handshake
92/// and negotiation phase. All of these error codes have bit 31 set (0x80000000) to
93/// distinguish them from successful replies.
94///
95/// Each error provides specific information about why an option request failed,
96/// allowing clients to make informed decisions about how to proceed.
97#[repr(u32)]
98#[derive(Debug, Error, IntEnum, PartialEq, Eq, Clone, Copy)]
99pub enum OptionReplyError {
100    /// The option sent by the client is unknown by this server implementation.
101    ///
102    /// This may occur because the server is too old or from another source
103    /// that doesn't support the requested option.
104    ///
105    /// Corresponds to NBD_REP_ERR_UNSUP (2^31 + 1).
106    #[error("Unsupported option (NBD_REP_ERR_UNSUP)")]
107    Unsupported = 0x80000001,
108
109    /// The option sent by the client is known but forbidden by server policy.
110    ///
111    /// The server recognizes the option and it's syntactically valid, but
112    /// server-side policy forbids the server to allow the option (e.g., the client
113    /// sent NBD_OPT_LIST but server configuration has that disabled).
114    ///
115    /// Corresponds to NBD_REP_ERR_POLICY (2^31 + 2).
116    #[error("Policy error (NBD_REP_ERR_POLICY)")]
117    Policy = 0x80000002,
118
119    /// The option sent by the client is known but syntactically or semantically invalid.
120    ///
121    /// For instance, the client sent an NBD_OPT_LIST with nonzero data length,
122    /// or the client sent a second NBD_OPT_STARTTLS after TLS was already negotiated.
123    ///
124    /// Corresponds to NBD_REP_ERR_INVALID (2^31 + 3).
125    #[error("Invalid option (NBD_REP_ERR_INVALID)")]
126    Invalid = 0x80000003,
127
128    /// The option is not supported on the platform where the server is running.
129    ///
130    /// This error occurs when an option requires compile-time options that
131    /// were disabled on the server, e.g., when trying to use TLS but the server
132    /// was built without TLS support.
133    ///
134    /// Corresponds to NBD_REP_ERR_PLATFORM (2^31 + 4).
135    #[error("Platform error (NBD_REP_ERR_PLATFORM)")]
136    Platform = 0x80000004,
137
138    /// The server requires TLS to be initiated before continuing negotiation.
139    ///
140    /// For NBD_OPT_INFO and NBD_OPT_GO, this unwillingness may be limited to
141    /// the export in question, depending on the TLS mode.
142    ///
143    /// Corresponds to NBD_REP_ERR_TLS_REQD (2^31 + 5).
144    #[error("TLS required (NBD_REP_ERR_TLS_REQD)")]
145    TLSRequired = 0x80000005,
146
147    /// The requested export is not available on the server.
148    ///
149    /// This is typically returned when a client attempts to connect to an export
150    /// that doesn't exist or isn't configured on the server.
151    ///
152    /// Corresponds to NBD_REP_ERR_UNKNOWN (2^31 + 6).
153    #[error("Unknown export (NBD_REP_ERR_UNKNOWN)")]
154    UnknownExport = 0x80000006,
155
156    /// The server is in the process of shutting down.
157    ///
158    /// The server is unwilling to continue negotiation as it is being shut down.
159    ///
160    /// Corresponds to NBD_REP_ERR_SHUTDOWN (2^31 + 7).
161    #[error("Server shutting down (NBD_REP_ERR_SHUTDOWN)")]
162    Shutdown = 0x80000007,
163
164    /// The server requires block size information before proceeding.
165    ///
166    /// The server is unwilling to enter transmission phase for a given export
167    /// unless the client first acknowledges (via NBD_INFO_BLOCK_SIZE) that it
168    /// will obey non-default block sizing requirements.
169    ///
170    /// Corresponds to NBD_REP_ERR_BLOCK_SIZE_REQD (2^31 + 8).
171    #[error("Block size required (NBD_REP_ERR_BLOCK_SIZE_REQD)")]
172    BlockSizeRequired = 0x80000008,
173
174    /// The request or reply is too large for the server to process.
175    ///
176    /// This can occur when a client sends a request that exceeds the server's
177    /// processing capabilities, or when a reply would be too large to send.
178    ///
179    /// Corresponds to NBD_REP_ERR_TOO_BIG (2^31 + 9).
180    #[error("Request too big (NBD_REP_ERR_TOO_BIG)")]
181    TooBig = 0x80000009,
182
183    /// The server requires extended headers for the operation.
184    ///
185    /// This is defined by the experimental EXTENDED_HEADERS extension to the NBD protocol.
186    ///
187    /// Corresponds to NBD_REP_ERR_EXT_HEADER_REQD (2^31 + 10).
188    #[error("Extended header required (NBD_REP_ERR_EXT_HEADER_REQD)")]
189    ExtendedHeaderRequired = 0x8000000A,
190}