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}