1 use crate::*; 2 3 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 4 pub enum IpDefragError { 5 /// Error if a payload lenght of a IP Fragment packet is not a multiple of 16 6 /// and the "more fragments" flag is set. 7 UnalignedFragmentPayloadLen { 8 offset: IpFragOffset, 9 payload_len: usize, 10 }, 11 12 /// Error if a segment is bigger then the maximum allowed size. 13 SegmentTooBig { 14 offset: IpFragOffset, 15 payload_len: usize, 16 max: u16, 17 }, 18 19 /// Error if multiple TP segments were received with the "more segment" 20 /// unset and differing end points. 21 ConflictingEnd { 22 /// Offset + tp_payload.len() of the previous package with "more segment" unset. 23 previous_end: u16, 24 25 /// Offset + tp_payload.len() of the current package. 26 conflicting_end: u16, 27 }, 28 29 /// Error if not enough memory could be allocated to store the TP payload. 30 AllocationFailure { len: usize }, 31 } 32 33 impl core::fmt::Display for IpDefragError { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 35 use IpDefragError::*; 36 match self { 37 UnalignedFragmentPayloadLen{ offset, payload_len } => write!(f, "Payload length {payload_len} of IP fragment (offset {offset}) is not a multiple of 8. This is only allowed for the last fragment packet."), 38 SegmentTooBig{ offset, payload_len, max } => write!(f, "Overall length of IP fragment (offset {offset}, payload len: {payload_len}) bigger then the maximum allowed size of {max}."), 39 ConflictingEnd { previous_end, conflicting_end } => write!(f, "Received a IP fragment (offset + len: {conflicting_end}) which conflicts a package that previously set the end to {previous_end}."), 40 AllocationFailure { len } => write!(f, "Failed to allocate {len} bytes of memory to reconstruct the fragmented IP packets."), 41 } 42 } 43 } 44 45 impl std::error::Error for IpDefragError {} 46 47 #[cfg(test)] 48 mod tests { 49 use super::IpDefragError::*; 50 use super::*; 51 use std::format; 52 53 #[test] debug()54 fn debug() { 55 let err = UnalignedFragmentPayloadLen { 56 offset: IpFragOffset::try_new(0).unwrap(), 57 payload_len: 16, 58 }; 59 let _ = format!("{err:?}"); 60 } 61 62 #[test] clone_eq_hash_ord()63 fn clone_eq_hash_ord() { 64 use core::cmp::Ordering; 65 use std::collections::hash_map::DefaultHasher; 66 use std::hash::{Hash, Hasher}; 67 68 let err = UnalignedFragmentPayloadLen { 69 offset: IpFragOffset::try_new(0).unwrap(), 70 payload_len: 16, 71 }; 72 assert_eq!(err, err.clone()); 73 let hash_a = { 74 let mut hasher = DefaultHasher::new(); 75 err.hash(&mut hasher); 76 hasher.finish() 77 }; 78 let hash_b = { 79 let mut hasher = DefaultHasher::new(); 80 err.clone().hash(&mut hasher); 81 hasher.finish() 82 }; 83 assert_eq!(hash_a, hash_b); 84 assert_eq!(Ordering::Equal, err.cmp(&err)); 85 assert_eq!(Some(Ordering::Equal), err.partial_cmp(&err)); 86 } 87 88 #[test] fmt()89 fn fmt() { 90 let tests = [ 91 (UnalignedFragmentPayloadLen { offset: IpFragOffset::try_new(0).unwrap(), payload_len: 2 }, "Payload length 2 of IP fragment (offset 0) is not a multiple of 8. This is only allowed for the last fragment packet."), 92 (SegmentTooBig { offset: IpFragOffset::try_new(0).unwrap(), payload_len: 2, max: 3, }, "Overall length of IP fragment (offset 0, payload len: 2) bigger then the maximum allowed size of 3."), 93 (ConflictingEnd { previous_end: 2, conflicting_end: 1 }, "Received a IP fragment (offset + len: 1) which conflicts a package that previously set the end to 2."), 94 (AllocationFailure { len: 0 }, "Failed to allocate 0 bytes of memory to reconstruct the fragmented IP packets."), 95 ]; 96 for test in tests { 97 assert_eq!(format!("{}", test.0), test.1); 98 } 99 } 100 101 #[test] source()102 fn source() { 103 use std::error::Error; 104 assert!(UnalignedFragmentPayloadLen { 105 offset: IpFragOffset::try_new(0).unwrap(), 106 payload_len: 16 107 } 108 .source() 109 .is_none()); 110 } 111 } 112