1 use crate::*; 2 use core::slice::from_raw_parts; 3 4 /// Allows iterating over the IPv6 extension headers present in an [Ipv6ExtensionsSlice]. 5 #[derive(Clone, Debug, Eq, PartialEq)] 6 pub struct Ipv6ExtensionSliceIter<'a> { 7 pub(crate) next_header: IpNumber, 8 pub(crate) rest: &'a [u8], 9 } 10 11 impl Default for Ipv6ExtensionSliceIter<'_> { default() -> Self12 fn default() -> Self { 13 Ipv6ExtensionSliceIter { 14 // don't use 0 as this is the reserved value 15 // for the hop by hop header 16 next_header: IpNumber::IPV6_NO_NEXT_HEADER, 17 rest: &[], 18 } 19 } 20 } 21 22 impl<'a> Iterator for Ipv6ExtensionSliceIter<'a> { 23 type Item = Ipv6ExtensionSlice<'a>; 24 next(&mut self) -> Option<Ipv6ExtensionSlice<'a>>25 fn next(&mut self) -> Option<Ipv6ExtensionSlice<'a>> { 26 use ip_number::*; 27 use Ipv6ExtensionSlice::*; 28 29 match self.next_header { 30 // Note on the unsafe calls: 31 // 32 // As the slice contents & length were previously checked by 33 // Ipv6ExtensionsSlice::from_slice the content does not have to be 34 // rechecked. 35 IPV6_HOP_BY_HOP => unsafe { 36 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest); 37 let len = slice.slice().len(); 38 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len); 39 self.next_header = slice.next_header(); 40 Some(HopByHop(slice)) 41 }, 42 IPV6_ROUTE => unsafe { 43 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest); 44 let len = slice.slice().len(); 45 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len); 46 self.next_header = slice.next_header(); 47 Some(Routing(slice)) 48 }, 49 IPV6_DEST_OPTIONS => unsafe { 50 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest); 51 let len = slice.slice().len(); 52 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len); 53 self.next_header = slice.next_header(); 54 Some(DestinationOptions(slice)) 55 }, 56 IPV6_FRAG => unsafe { 57 let slice = Ipv6FragmentHeaderSlice::from_slice_unchecked(self.rest); 58 let len = slice.slice().len(); 59 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len); 60 self.next_header = slice.next_header(); 61 62 Some(Fragment(slice)) 63 }, 64 AUTH => unsafe { 65 let slice = IpAuthHeaderSlice::from_slice_unchecked(self.rest); 66 let len = slice.slice().len(); 67 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len); 68 self.next_header = slice.next_header(); 69 Some(Authentication(slice)) 70 }, 71 // done parsing, the next header is not a known/supported header extension 72 _ => None, 73 } 74 } 75 } 76 77 #[cfg(test)] 78 mod test { 79 use super::ipv6_exts_test_helpers::*; 80 use super::*; 81 use crate::ip_number::*; 82 use crate::test_gens::*; 83 use alloc::borrow::ToOwned; 84 use proptest::prelude::*; 85 86 #[test] into_iter()87 fn into_iter() { 88 let a: Ipv6ExtensionsSlice = Default::default(); 89 let mut iter = a.into_iter(); 90 assert_eq!(None, iter.next()); 91 } 92 93 proptest! { 94 #[test] 95 fn next( 96 header_size in any::<u8>(), 97 post_header in ip_number_any() 98 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(), 99 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x) 100 ) 101 ) { 102 /// Run a test with the given ip numbers 103 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) { 104 // setup test payload 105 let e = ExtensionTestPayload::new( 106 ip_numbers, 107 header_sizes 108 ); 109 110 // a hop by hop header that is not at the start triggers an error 111 if false == e.ip_numbers[1..].iter().any(|&x| x == IPV6_HOP_BY_HOP) { 112 // normal read 113 let (header, _, _) = Ipv6ExtensionsSlice::from_slice(ip_numbers[0], e.slice()).unwrap(); 114 let mut iter = header.into_iter(); 115 let mut slice = e.slice(); 116 117 // go through all expected headers 118 for i in 0..e.ip_numbers.len() - 1 { 119 use Ipv6ExtensionSlice::*; 120 121 // iterate and check all results 122 let next = iter.next().unwrap(); 123 match e.ip_numbers[i] { 124 IPV6_HOP_BY_HOP => { 125 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap(); 126 assert_eq!(next, HopByHop(header.clone())); 127 slice = &slice[header.slice().len()..]; 128 }, 129 IPV6_ROUTE => { 130 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap(); 131 assert_eq!(next, Routing(header.clone())); 132 slice = &slice[header.slice().len()..]; 133 }, 134 IPV6_DEST_OPTIONS => { 135 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap(); 136 assert_eq!(next, DestinationOptions(header.clone())); 137 slice = &slice[header.slice().len()..]; 138 } 139 IPV6_FRAG => { 140 let header = Ipv6FragmentHeaderSlice::from_slice(slice).unwrap(); 141 assert_eq!(next, Fragment(header.clone())); 142 slice = &slice[header.slice().len()..]; 143 }, 144 AUTH => { 145 let header = IpAuthHeaderSlice::from_slice(slice).unwrap(); 146 assert_eq!(next, Authentication(header.clone())); 147 slice = &slice[header.slice().len()..]; 148 }, 149 _ => unreachable!() 150 } 151 } 152 153 // expect that all headers have been visited 154 assert_eq!(None, iter.next()); 155 } 156 } 157 158 // test the parsing of different extension header combinations 159 for first_header in &EXTENSION_KNOWN_IP_NUMBERS { 160 161 // single header parsing 162 run_test( 163 &[*first_header, post_header], 164 &[header_size], 165 ); 166 167 for second_header in &EXTENSION_KNOWN_IP_NUMBERS { 168 169 // double header parsing 170 run_test( 171 &[*first_header, *second_header, post_header], 172 &[header_size], 173 ); 174 175 for third_header in &EXTENSION_KNOWN_IP_NUMBERS { 176 // tripple header parsing 177 run_test( 178 &[*first_header, *second_header, *third_header, post_header], 179 &[header_size], 180 ); 181 } 182 } 183 } 184 } 185 } 186 187 #[test] debug()188 fn debug() { 189 use alloc::format; 190 191 let a: Ipv6ExtensionSliceIter = Default::default(); 192 assert_eq!( 193 format!( 194 "Ipv6ExtensionSliceIter {{ next_header: {:?}, rest: [] }}", 195 IpNumber(59) 196 ), 197 format!("{:?}", a) 198 ); 199 } 200 201 #[test] clone_eq()202 fn clone_eq() { 203 let a: Ipv6ExtensionSliceIter = Default::default(); 204 assert_eq!(a.clone(), a); 205 } 206 207 #[test] default()208 fn default() { 209 let mut a: Ipv6ExtensionSliceIter = Default::default(); 210 assert_eq!(None, a.next()); 211 } 212 } 213