1 use crate::*; 2 3 /// Error when slicing an packet from downwards (both 4 /// starting from ethernet or ip layer downwards). 5 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 pub enum SliceError { 7 /// Length related errors (e.g. not enough data in slice). 8 Len(err::LenError), 9 /// Error when decoding an Linux SLL header. 10 LinuxSll(err::linux_sll::HeaderError), 11 /// Error when decoding starting at an IP header (v4 or v6). 12 Ip(err::ip::HeaderError), 13 /// Error when decoding an IPv4 header. 14 Ipv4(err::ipv4::HeaderError), 15 /// Error when decoding an IPv6 header. 16 Ipv6(err::ipv6::HeaderError), 17 /// Error when decoding an IPv4 extension header. 18 Ipv4Exts(err::ip_auth::HeaderError), 19 /// Error when decoding an IPv6 extension header. 20 Ipv6Exts(err::ipv6_exts::HeaderError), 21 /// Error when decoding a TCP header. 22 Tcp(err::tcp::HeaderError), 23 } 24 25 impl core::fmt::Display for SliceError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 27 use SliceError::*; 28 29 match self { 30 Len(err) => err.fmt(f), 31 LinuxSll(err) => err.fmt(f), 32 Ip(err) => err.fmt(f), 33 Ipv4(err) => err.fmt(f), 34 Ipv6(err) => err.fmt(f), 35 Ipv4Exts(err) => err.fmt(f), 36 Ipv6Exts(err) => err.fmt(f), 37 Tcp(err) => err.fmt(f), 38 } 39 } 40 } 41 42 #[cfg(feature = "std")] 43 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 44 impl std::error::Error for SliceError { source(&self) -> Option<&(dyn std::error::Error + 'static)>45 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 46 use SliceError::*; 47 match self { 48 Len(err) => Some(err), 49 LinuxSll(err) => Some(err), 50 Ip(err) => Some(err), 51 Ipv4(err) => Some(err), 52 Ipv6(err) => Some(err), 53 Ipv4Exts(err) => Some(err), 54 Ipv6Exts(err) => Some(err), 55 Tcp(err) => Some(err), 56 } 57 } 58 } 59 60 #[cfg(test)] 61 mod tests { 62 use super::{SliceError::*, *}; 63 use crate::err::Layer; 64 use alloc::format; 65 use std::{ 66 collections::hash_map::DefaultHasher, 67 error::Error, 68 hash::{Hash, Hasher}, 69 }; 70 71 #[test] debug()72 fn debug() { 73 let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 }; 74 assert_eq!( 75 format!("Ipv4({:?})", err.clone()), 76 format!("{:?}", Ipv4(err)) 77 ); 78 } 79 80 #[test] clone_eq_hash()81 fn clone_eq_hash() { 82 let err = Ipv4(err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 }); 83 assert_eq!(err, err.clone()); 84 let hash_a = { 85 let mut hasher = DefaultHasher::new(); 86 err.hash(&mut hasher); 87 hasher.finish() 88 }; 89 let hash_b = { 90 let mut hasher = DefaultHasher::new(); 91 err.clone().hash(&mut hasher); 92 hasher.finish() 93 }; 94 assert_eq!(hash_a, hash_b); 95 } 96 97 #[test] fmt()98 fn fmt() { 99 // Len 100 { 101 let err = err::LenError { 102 required_len: 2, 103 len: 1, 104 len_source: LenSource::Slice, 105 layer: Layer::TcpHeader, 106 layer_start_offset: 3, 107 }; 108 assert_eq!(format!("{}", err), format!("{}", Len(err))); 109 } 110 111 // Linux SLL Header 112 { 113 let err = err::linux_sll::HeaderError::UnsupportedArpHardwareId { 114 arp_hardware_type: ArpHardwareId::ADAPT, 115 }; 116 assert_eq!( 117 format!("{}", err), 118 format!("{}", err::packet::SliceError::LinuxSll(err)) 119 ); 120 } 121 122 // IpHeader 123 { 124 let err = err::ip::HeaderError::UnsupportedIpVersion { version_number: 1 }; 125 assert_eq!( 126 format!("{}", err), 127 format!("{}", err::packet::SliceError::Ip(err)) 128 ); 129 } 130 131 // Ipv4Header 132 { 133 let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 }; 134 assert_eq!(format!("{}", err), format!("{}", Ipv4(err))); 135 } 136 137 // Ipv6Header 138 { 139 let err = err::ipv6::HeaderError::UnexpectedVersion { version_number: 1 }; 140 assert_eq!(format!("{}", err), format!("{}", Ipv6(err))); 141 } 142 143 // Ipv4ExtHeader 144 { 145 let err = err::ip_auth::HeaderError::ZeroPayloadLen; 146 assert_eq!(format!("{}", err), format!("{}", Ipv4Exts(err))); 147 } 148 149 // Ipv6ExtHeader 150 { 151 let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart; 152 assert_eq!(format!("{}", err), format!("{}", Ipv6Exts(err))); 153 }; 154 155 // TcpHeader 156 { 157 let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 1 }; 158 assert_eq!(format!("{}", err), format!("{}", Tcp(err))); 159 } 160 } 161 162 #[cfg(feature = "std")] 163 #[test] source()164 fn source() { 165 // Len 166 { 167 let err = err::LenError { 168 required_len: 2, 169 len: 1, 170 len_source: LenSource::Slice, 171 layer: Layer::TcpHeader, 172 layer_start_offset: 3, 173 }; 174 assert!(Len(err).source().is_some()); 175 } 176 177 // IpHeaders 178 { 179 let err = err::linux_sll::HeaderError::UnsupportedArpHardwareId { 180 arp_hardware_type: ArpHardwareId::ETHERNET, 181 }; 182 assert!(LinuxSll(err).source().is_some()); 183 } 184 185 // IpHeaders 186 { 187 let err = err::ip::HeaderError::UnsupportedIpVersion { version_number: 1 }; 188 assert!(Ip(err).source().is_some()); 189 } 190 191 // Ipv4Header 192 { 193 let err = err::ipv4::HeaderError::UnexpectedVersion { version_number: 1 }; 194 assert!(Ipv4(err).source().is_some()); 195 } 196 197 // Ipv6Header 198 { 199 let err = err::ipv6::HeaderError::UnexpectedVersion { version_number: 1 }; 200 assert!(Ipv6(err).source().is_some()); 201 } 202 203 // Ipv4ExtHeader 204 { 205 let err = err::ip_auth::HeaderError::ZeroPayloadLen; 206 assert!(Ipv4Exts(err).source().is_some()); 207 } 208 209 // Ipv6ExtHeader 210 { 211 let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart; 212 assert!(Ipv6Exts(err).source().is_some()); 213 }; 214 215 // TcpHeader 216 { 217 let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 1 }; 218 assert!(Tcp(err).source().is_some()); 219 } 220 } 221 } 222