Skip to main content

ruvix_net/
error.rs

1//! Network error types.
2//!
3//! All network operations return `Result<T, NetError>` to indicate success or failure.
4//! Errors are designed to be informative for debugging network issues.
5
6use ruvix_types::KernelError;
7
8/// Network error codes.
9///
10/// These errors cover all network stack operations from Ethernet to UDP.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[repr(u16)]
13pub enum NetError {
14    /// The packet is too short to contain the expected header.
15    PacketTooShort = 1,
16
17    /// The packet exceeds the maximum allowed size.
18    PacketTooLarge = 2,
19
20    /// Invalid Ethernet frame format.
21    InvalidEthernetFrame = 3,
22
23    /// Unknown or unsupported EtherType.
24    UnsupportedEtherType = 4,
25
26    /// Invalid IPv4 header format or checksum.
27    InvalidIpv4Header = 5,
28
29    /// IPv4 header checksum mismatch.
30    Ipv4ChecksumError = 6,
31
32    /// IPv4 version is not 4.
33    InvalidIpVersion = 7,
34
35    /// IPv4 header length is invalid.
36    InvalidIpHeaderLength = 8,
37
38    /// IPv4 Time To Live expired.
39    TtlExpired = 9,
40
41    /// Invalid UDP header format or checksum.
42    InvalidUdpHeader = 10,
43
44    /// UDP checksum mismatch.
45    UdpChecksumError = 11,
46
47    /// Invalid ICMP header format.
48    InvalidIcmpHeader = 12,
49
50    /// Invalid ARP packet format.
51    InvalidArpPacket = 13,
52
53    /// No ARP entry found for the target IP.
54    ArpNotFound = 14,
55
56    /// ARP cache is full.
57    ArpCacheFull = 15,
58
59    /// The socket is not bound to a port.
60    SocketNotBound = 16,
61
62    /// The port is already in use.
63    PortInUse = 17,
64
65    /// No available ports for ephemeral allocation.
66    NoPortsAvailable = 18,
67
68    /// The destination is unreachable.
69    DestinationUnreachable = 19,
70
71    /// Network device error.
72    DeviceError = 20,
73
74    /// The provided buffer is too small.
75    BufferTooSmall = 21,
76
77    /// Operation would block (non-blocking mode).
78    WouldBlock = 22,
79
80    /// Invalid port number (0 for source).
81    InvalidPort = 23,
82
83    /// Fragment reassembly not supported.
84    FragmentationNotSupported = 24,
85
86    /// Kernel error passthrough.
87    KernelError(u16) = 255,
88}
89
90impl NetError {
91    /// Returns a human-readable description of the error.
92    #[inline]
93    #[must_use]
94    pub const fn as_str(&self) -> &'static str {
95        match self {
96            Self::PacketTooShort => "Packet too short for header",
97            Self::PacketTooLarge => "Packet exceeds maximum size",
98            Self::InvalidEthernetFrame => "Invalid Ethernet frame format",
99            Self::UnsupportedEtherType => "Unsupported EtherType",
100            Self::InvalidIpv4Header => "Invalid IPv4 header",
101            Self::Ipv4ChecksumError => "IPv4 checksum mismatch",
102            Self::InvalidIpVersion => "Invalid IP version (expected 4)",
103            Self::InvalidIpHeaderLength => "Invalid IP header length",
104            Self::TtlExpired => "TTL expired",
105            Self::InvalidUdpHeader => "Invalid UDP header",
106            Self::UdpChecksumError => "UDP checksum mismatch",
107            Self::InvalidIcmpHeader => "Invalid ICMP header",
108            Self::InvalidArpPacket => "Invalid ARP packet",
109            Self::ArpNotFound => "ARP entry not found",
110            Self::ArpCacheFull => "ARP cache full",
111            Self::SocketNotBound => "Socket not bound",
112            Self::PortInUse => "Port already in use",
113            Self::NoPortsAvailable => "No ephemeral ports available",
114            Self::DestinationUnreachable => "Destination unreachable",
115            Self::DeviceError => "Network device error",
116            Self::BufferTooSmall => "Buffer too small",
117            Self::WouldBlock => "Operation would block",
118            Self::InvalidPort => "Invalid port number",
119            Self::FragmentationNotSupported => "IP fragmentation not supported",
120            Self::KernelError(_) => "Kernel error",
121        }
122    }
123
124    /// Returns the error code as a u16 (for unit variants).
125    #[inline]
126    #[must_use]
127    pub const fn code(&self) -> u16 {
128        match self {
129            Self::PacketTooShort => 1,
130            Self::PacketTooLarge => 2,
131            Self::InvalidEthernetFrame => 3,
132            Self::UnsupportedEtherType => 4,
133            Self::InvalidIpv4Header => 5,
134            Self::Ipv4ChecksumError => 6,
135            Self::InvalidIpVersion => 7,
136            Self::InvalidIpHeaderLength => 8,
137            Self::TtlExpired => 9,
138            Self::InvalidUdpHeader => 10,
139            Self::UdpChecksumError => 11,
140            Self::InvalidIcmpHeader => 12,
141            Self::InvalidArpPacket => 13,
142            Self::ArpNotFound => 14,
143            Self::ArpCacheFull => 15,
144            Self::SocketNotBound => 16,
145            Self::PortInUse => 17,
146            Self::NoPortsAvailable => 18,
147            Self::DestinationUnreachable => 19,
148            Self::DeviceError => 20,
149            Self::BufferTooSmall => 21,
150            Self::WouldBlock => 22,
151            Self::InvalidPort => 23,
152            Self::FragmentationNotSupported => 24,
153            Self::KernelError(code) => *code,
154        }
155    }
156
157    /// Converts from a raw u16 error code.
158    #[inline]
159    #[must_use]
160    pub const fn from_u16(code: u16) -> Option<Self> {
161        match code {
162            1 => Some(Self::PacketTooShort),
163            2 => Some(Self::PacketTooLarge),
164            3 => Some(Self::InvalidEthernetFrame),
165            4 => Some(Self::UnsupportedEtherType),
166            5 => Some(Self::InvalidIpv4Header),
167            6 => Some(Self::Ipv4ChecksumError),
168            7 => Some(Self::InvalidIpVersion),
169            8 => Some(Self::InvalidIpHeaderLength),
170            9 => Some(Self::TtlExpired),
171            10 => Some(Self::InvalidUdpHeader),
172            11 => Some(Self::UdpChecksumError),
173            12 => Some(Self::InvalidIcmpHeader),
174            13 => Some(Self::InvalidArpPacket),
175            14 => Some(Self::ArpNotFound),
176            15 => Some(Self::ArpCacheFull),
177            16 => Some(Self::SocketNotBound),
178            17 => Some(Self::PortInUse),
179            18 => Some(Self::NoPortsAvailable),
180            19 => Some(Self::DestinationUnreachable),
181            20 => Some(Self::DeviceError),
182            21 => Some(Self::BufferTooSmall),
183            22 => Some(Self::WouldBlock),
184            23 => Some(Self::InvalidPort),
185            24 => Some(Self::FragmentationNotSupported),
186            _ => None,
187        }
188    }
189}
190
191impl From<KernelError> for NetError {
192    fn from(err: KernelError) -> Self {
193        Self::KernelError(err as u16)
194    }
195}
196
197/// Result type for network operations.
198pub type NetResult<T> = Result<T, NetError>;
199
200#[cfg(test)]
201mod tests {
202    use super::*;
203
204    #[test]
205    fn test_error_roundtrip() {
206        let errors = [
207            NetError::PacketTooShort,
208            NetError::InvalidEthernetFrame,
209            NetError::ArpNotFound,
210            NetError::WouldBlock,
211        ];
212
213        for err in errors {
214            let code = err.code();
215            let parsed = NetError::from_u16(code).unwrap();
216            assert_eq!(err, parsed);
217        }
218    }
219
220    #[test]
221    fn test_error_as_str() {
222        assert_eq!(NetError::PacketTooShort.as_str(), "Packet too short for header");
223        assert_eq!(NetError::ArpNotFound.as_str(), "ARP entry not found");
224    }
225
226    #[test]
227    fn test_kernel_error_conversion() {
228        let kernel_err = KernelError::OutOfMemory;
229        let net_err: NetError = kernel_err.into();
230        assert!(matches!(net_err, NetError::KernelError(5)));
231    }
232}