1use ruvix_types::KernelError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[repr(u16)]
13pub enum NetError {
14 PacketTooShort = 1,
16
17 PacketTooLarge = 2,
19
20 InvalidEthernetFrame = 3,
22
23 UnsupportedEtherType = 4,
25
26 InvalidIpv4Header = 5,
28
29 Ipv4ChecksumError = 6,
31
32 InvalidIpVersion = 7,
34
35 InvalidIpHeaderLength = 8,
37
38 TtlExpired = 9,
40
41 InvalidUdpHeader = 10,
43
44 UdpChecksumError = 11,
46
47 InvalidIcmpHeader = 12,
49
50 InvalidArpPacket = 13,
52
53 ArpNotFound = 14,
55
56 ArpCacheFull = 15,
58
59 SocketNotBound = 16,
61
62 PortInUse = 17,
64
65 NoPortsAvailable = 18,
67
68 DestinationUnreachable = 19,
70
71 DeviceError = 20,
73
74 BufferTooSmall = 21,
76
77 WouldBlock = 22,
79
80 InvalidPort = 23,
82
83 FragmentationNotSupported = 24,
85
86 KernelError(u16) = 255,
88}
89
90impl NetError {
91 #[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 #[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 #[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
197pub 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}