1 use crate::*; 2 3 /// Allows iterating over the options after a TCP header. 4 #[derive(Clone, Eq, PartialEq)] 5 pub struct TcpOptionsIterator<'a> { 6 pub(crate) options: &'a [u8], 7 } 8 9 impl<'a> TcpOptionsIterator<'a> { 10 /// Creates an options iterator from a slice containing encoded tcp options. from_slice(options: &'a [u8]) -> TcpOptionsIterator<'a>11 pub fn from_slice(options: &'a [u8]) -> TcpOptionsIterator<'a> { 12 TcpOptionsIterator { options } 13 } 14 15 /// Returns the non processed part of the options slice. rest(&self) -> &'a [u8]16 pub fn rest(&self) -> &'a [u8] { 17 self.options 18 } 19 } 20 21 impl Iterator for TcpOptionsIterator<'_> { 22 type Item = Result<TcpOptionElement, TcpOptionReadError>; 23 next(&mut self) -> Option<Self::Item>24 fn next(&mut self) -> Option<Self::Item> { 25 use crate::TcpOptionElement::*; 26 use crate::TcpOptionReadError::*; 27 28 let expect_specific_size = 29 |expected_size: u8, slice: &[u8]| -> Result<(), TcpOptionReadError> { 30 let id = slice[0]; 31 if slice.len() < expected_size as usize { 32 Err(UnexpectedEndOfSlice { 33 option_id: id, 34 expected_len: expected_size, 35 actual_len: slice.len(), 36 }) 37 } else if slice[1] != expected_size { 38 Err(UnexpectedSize { 39 option_id: slice[0], 40 size: slice[1], 41 }) 42 } else { 43 Ok(()) 44 } 45 }; 46 47 if self.options.is_empty() { 48 None 49 } else { 50 //first determine the result 51 use tcp_option::*; 52 let result = match self.options[0] { 53 //end 54 KIND_END => None, 55 KIND_NOOP => { 56 self.options = &self.options[1..]; 57 Some(Ok(Noop)) 58 } 59 KIND_MAXIMUM_SEGMENT_SIZE => { 60 match expect_specific_size(LEN_MAXIMUM_SEGMENT_SIZE, self.options) { 61 Err(value) => Some(Err(value)), 62 _ => { 63 // SAFETY: 64 // Safe as the slice size is checked beforehand to be at 65 // least of size LEN_MAXIMUM_SEGMENT_SIZE (4). 66 let value = 67 unsafe { get_unchecked_be_u16(self.options.as_ptr().add(2)) }; 68 self.options = &self.options[4..]; 69 Some(Ok(MaximumSegmentSize(value))) 70 } 71 } 72 } 73 KIND_WINDOW_SCALE => match expect_specific_size(LEN_WINDOW_SCALE, self.options) { 74 Err(value) => Some(Err(value)), 75 _ => { 76 let value = self.options[2]; 77 self.options = &self.options[3..]; 78 Some(Ok(WindowScale(value))) 79 } 80 }, 81 KIND_SELECTIVE_ACK_PERMITTED => { 82 match expect_specific_size(LEN_SELECTIVE_ACK_PERMITTED, self.options) { 83 Err(value) => Some(Err(value)), 84 _ => { 85 self.options = &self.options[2..]; 86 Some(Ok(SelectiveAcknowledgementPermitted)) 87 } 88 } 89 } 90 KIND_SELECTIVE_ACK => { 91 //check that the length field can be read 92 if self.options.len() < 2 { 93 Some(Err(UnexpectedEndOfSlice { 94 option_id: self.options[0], 95 expected_len: 2, 96 actual_len: self.options.len(), 97 })) 98 } else { 99 //check that the length is an allowed one for this option 100 let len = self.options[1]; 101 if len != 10 && len != 18 && len != 26 && len != 34 { 102 Some(Err(UnexpectedSize { 103 option_id: self.options[0], 104 size: len, 105 })) 106 } else if self.options.len() < (len as usize) { 107 Some(Err(UnexpectedEndOfSlice { 108 option_id: self.options[0], 109 expected_len: len, 110 actual_len: self.options.len(), 111 })) 112 } else { 113 let mut acks: [Option<(u32, u32)>; 3] = [None; 3]; 114 // SAFETY: 115 // This is safe as above the len is checked 116 // to be at least 10 and the slice len is 117 // checked to be at least len bytes. 118 let first = unsafe { 119 ( 120 get_unchecked_be_u32(self.options.as_ptr().add(2)), 121 get_unchecked_be_u32(self.options.as_ptr().add(6)), 122 ) 123 }; 124 for (i, item) in acks.iter_mut().enumerate().take(3) { 125 let offset = 2 + 8 + (i * 8); 126 // SAFETY: 127 // len can only be 10, 18, 26 or 34 128 // therefore if the offset is smaller then the 129 // len, then at least 8 bytes can be read. 130 unsafe { 131 if offset < (len as usize) { 132 *item = Some(( 133 get_unchecked_be_u32(self.options.as_ptr().add(offset)), 134 get_unchecked_be_u32( 135 self.options.as_ptr().add(offset + 4), 136 ), 137 )); 138 } 139 } 140 } 141 //iterate the options 142 self.options = &self.options[len as usize..]; 143 Some(Ok(SelectiveAcknowledgement(first, acks))) 144 } 145 } 146 } 147 KIND_TIMESTAMP => { 148 match expect_specific_size(LEN_TIMESTAMP, self.options) { 149 Err(value) => Some(Err(value)), 150 151 _ => unsafe { 152 let t = Timestamp( 153 // SAFETY: 154 // Safe as the len first gets checked to be equal 155 // LEN_TIMESTAMP (10). 156 get_unchecked_be_u32(self.options.as_ptr().add(2)), 157 get_unchecked_be_u32(self.options.as_ptr().add(6)), 158 ); 159 self.options = &self.options[10..]; 160 Some(Ok(t)) 161 }, 162 } 163 } 164 165 //unknown id 166 _ => Some(Err(UnknownId(self.options[0]))), 167 }; 168 169 //in case the result was an error or the end move the slice to an end position 170 match result { 171 None | Some(Err(_)) => { 172 let len = self.options.len(); 173 self.options = &self.options[len..len]; 174 } 175 _ => {} 176 } 177 178 //finally return the result 179 result 180 } 181 } 182 } 183 184 impl core::fmt::Debug for TcpOptionsIterator<'_> { fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error>185 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { 186 let mut list = fmt.debug_list(); 187 188 // create a copy and iterate over all elements 189 for it in self.clone() { 190 match it { 191 Ok(e) => { 192 list.entry(&e); 193 } 194 Err(e) => { 195 list.entry(&Result::<(), TcpOptionReadError>::Err(e.clone())); 196 } 197 } 198 } 199 200 list.finish() 201 } 202 } 203 204 #[cfg(test)] 205 mod test { 206 use crate::{tcp_option::*, *}; 207 use alloc::format; 208 209 #[test] debug()210 fn debug() { 211 use tcp_option::*; 212 #[rustfmt::skip] 213 assert_eq!( 214 "[MaximumSegmentSize(0), WindowScale(0)]", 215 format!( 216 "{:?}", 217 TcpOptionsIterator::from_slice(&[ 218 KIND_MAXIMUM_SEGMENT_SIZE, 4, 0, 0, 219 KIND_WINDOW_SCALE, 3, 0, 220 KIND_END, 221 ]) 222 ) 223 ); 224 #[rustfmt::skip] 225 assert_eq!( 226 "[MaximumSegmentSize(0), Err(UnexpectedSize { option_id: 3, size: 0 })]", 227 format!( 228 "{:?}", 229 TcpOptionsIterator::from_slice(&[ 230 KIND_MAXIMUM_SEGMENT_SIZE, 4, 0, 0, 231 KIND_WINDOW_SCALE, 0, 0, 0, 232 ]) 233 ) 234 ); 235 } 236 237 #[test] clone_eq()238 fn clone_eq() { 239 use tcp_option::*; 240 let it = TcpOptionsIterator::from_slice(&[KIND_END]); 241 assert_eq!(it, it.clone()); 242 } 243 244 #[test] from_slice_and_rest()245 fn from_slice_and_rest() { 246 let buffer = [KIND_NOOP, KIND_NOOP, KIND_MAXIMUM_SEGMENT_SIZE, 4]; 247 let it = TcpOptionsIterator::from_slice(&buffer); 248 assert_eq!(it.rest(), &buffer[..]); 249 } 250 251 #[test] 252 #[rustfmt::skip] next()253 fn next() { 254 use crate::TcpOptionElement::*; 255 256 // ok test 257 { 258 fn expect_elements(buffer: &[u8], expected: &[TcpOptionElement]) { 259 // options iterator via from_slice() 260 let mut it = TcpOptionsIterator::from_slice(buffer); 261 for element in expected.iter() { 262 assert_eq!(element, &it.next().unwrap().unwrap()); 263 } 264 265 //expect no more elements 266 assert_eq!(None, it.next()); 267 assert_eq!(0, it.rest().len()); 268 } 269 270 // nop & max segment size 271 #[rustfmt::skip] 272 expect_elements(&[ 273 KIND_NOOP, 274 KIND_NOOP, 275 KIND_MAXIMUM_SEGMENT_SIZE, 4, 276 0, 1, 277 KIND_WINDOW_SCALE, 3, 2, 278 KIND_SELECTIVE_ACK_PERMITTED, 2, 279 KIND_SELECTIVE_ACK, 10, 280 0, 0, 0, 10, 281 0, 0, 0, 11, 282 KIND_SELECTIVE_ACK, 18, 283 0, 0, 0, 12, 284 0, 0, 0, 13, 285 0, 0, 0, 14, 286 0, 0, 0, 15, 287 KIND_SELECTIVE_ACK, 26, 288 0, 0, 0, 16, 289 0, 0, 0, 17, 290 0, 0, 0, 18, 291 0, 0, 0, 19, 292 0, 0, 0, 20, 293 0, 0, 0, 21, 294 KIND_SELECTIVE_ACK, 34, 295 0, 0, 0, 22, 296 0, 0, 0, 23, 297 0, 0, 0, 24, 298 0, 0, 0, 25, 299 0, 0, 0, 26, 300 0, 0, 0, 27, 301 0, 0, 0, 28, 302 0, 0, 0, 29, 303 KIND_TIMESTAMP, 10, 304 0, 0, 0, 30, 305 0, 0, 0, 31, 306 KIND_END, 0, 0, 0, 0 307 ], 308 &[ 309 Noop, 310 Noop, 311 MaximumSegmentSize(1), 312 WindowScale(2), 313 SelectiveAcknowledgementPermitted, 314 SelectiveAcknowledgement((10,11), [None, None, None]), 315 SelectiveAcknowledgement((12,13), [Some((14,15)), None, None]), 316 SelectiveAcknowledgement((16,17), [Some((18,19)), Some((20,21)), None]), 317 SelectiveAcknowledgement((22,23), [Some((24,25)), Some((26,27)), Some((28,29))]), 318 Timestamp(30,31) 319 ] 320 ); 321 } 322 323 // unknown id 324 { 325 let data = [255, 2, 0, 0, 0, 326 0, 0, 0, 0, 0, //10 327 0, 0, 0, 0, 0, 328 0, 0, 0, 0, 0, //20 329 0, 0, 0, 0, 0, 330 0, 0, 0, 0, 0, //30 331 0, 0, 0, 0]; 332 let mut it = TcpOptionsIterator::from_slice(&data); 333 assert_eq!(Some(Err(TcpOptionReadError::UnknownId(255))), it.next()); 334 335 //expect the iterator slice to be moved to the end 336 assert_eq!(0, it.rest().len()); 337 assert_eq!(None, it.next()); 338 assert_eq!(0, it.rest().len()); 339 } 340 341 // unexpected end of slice 342 { 343 fn expect_unexpected_eos(slice: &[u8]) { 344 for i in 1..slice.len()-1 { 345 let mut it = TcpOptionsIterator::from_slice(&slice[..i]); 346 assert_eq!( 347 Some( 348 Err( 349 TcpOptionReadError::UnexpectedEndOfSlice{ 350 option_id: slice[0], 351 expected_len: match slice[0] { 352 KIND_MAXIMUM_SEGMENT_SIZE => 4, 353 KIND_WINDOW_SCALE => 3, 354 KIND_SELECTIVE_ACK_PERMITTED => 2, 355 KIND_SELECTIVE_ACK => if i < 2 { 356 // the inial check only checks if there 357 // is enough data to read the length field 358 2 359 } else { 360 slice[1] 361 }, 362 KIND_TIMESTAMP => 10, 363 _ => panic!("not part of the tests"), 364 }, 365 actual_len: i 366 } 367 ) 368 ), 369 it.next() 370 ); 371 //expect the iterator slice to be moved to the end 372 assert_eq!(0, it.rest().len()); 373 assert_eq!(None, it.next()); 374 } 375 } 376 377 expect_unexpected_eos(&[KIND_MAXIMUM_SEGMENT_SIZE, 4, 0, 0]); 378 expect_unexpected_eos(&[KIND_WINDOW_SCALE, 3, 0]); 379 expect_unexpected_eos(&[KIND_MAXIMUM_SEGMENT_SIZE, 4, 0, 0]); 380 expect_unexpected_eos(&[KIND_SELECTIVE_ACK_PERMITTED, 2]); 381 expect_unexpected_eos(&[KIND_SELECTIVE_ACK, 10, 0, 0, 0, 382 0, 0, 0, 0, 0]); 383 expect_unexpected_eos(&[KIND_SELECTIVE_ACK, 18, 0, 0, 0, 384 0, 0, 0, 0, 0, 385 0, 0, 0, 0, 0, 386 0, 0, 0]); 387 expect_unexpected_eos(&[KIND_SELECTIVE_ACK, 26, 0, 0, 0, 388 0, 0, 0, 0, 0, 389 0, 0, 0, 0, 0, 390 0, 0, 0, 0, 0, 391 0, 0, 0, 0, 0, 392 0]); 393 expect_unexpected_eos(&[KIND_SELECTIVE_ACK, 34, 0, 0, 0, 394 0, 0, 0, 0, 0, //10 395 0, 0, 0, 0, 0, 396 0, 0, 0, 0, 0, //20 397 0, 0, 0, 0, 0, 398 0, 0, 0, 0, 0, //30 399 0, 0, 0, 0]); 400 expect_unexpected_eos(&[KIND_TIMESTAMP, 10, 0, 0, 0, 401 0, 0, 0, 0, 0]); 402 } 403 404 // unexpected option size error 405 { 406 fn expect_unexpected_size(id: u8, size: u8) { 407 let data = [ 408 id, size, 0, 0, 0, 0, 0, 0, 0, 0, //10 409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20 410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 411 0, 0, 0, 0, 412 ]; 413 let mut it = TcpOptionsIterator::from_slice(&data); 414 assert_eq!( 415 Some(Err(TcpOptionReadError::UnexpectedSize { 416 option_id: data[0], 417 size: data[1] 418 })), 419 it.next() 420 ); 421 //expect the iterator slice to be moved to the end 422 assert_eq!(0, it.rest().len()); 423 assert_eq!(None, it.next()); 424 assert_eq!(0, it.rest().len()); 425 } 426 expect_unexpected_size(KIND_MAXIMUM_SEGMENT_SIZE, 3); 427 expect_unexpected_size(KIND_MAXIMUM_SEGMENT_SIZE, 5); 428 429 expect_unexpected_size(KIND_WINDOW_SCALE, 2); 430 expect_unexpected_size(KIND_WINDOW_SCALE, 4); 431 432 expect_unexpected_size(KIND_MAXIMUM_SEGMENT_SIZE, 3); 433 expect_unexpected_size(KIND_MAXIMUM_SEGMENT_SIZE, 5); 434 435 expect_unexpected_size(KIND_SELECTIVE_ACK_PERMITTED, 1); 436 expect_unexpected_size(KIND_SELECTIVE_ACK_PERMITTED, 3); 437 438 expect_unexpected_size(KIND_SELECTIVE_ACK, 9); 439 expect_unexpected_size(KIND_SELECTIVE_ACK, 11); 440 441 expect_unexpected_size(KIND_SELECTIVE_ACK, 17); 442 expect_unexpected_size(KIND_SELECTIVE_ACK, 19); 443 444 expect_unexpected_size(KIND_SELECTIVE_ACK, 25); 445 expect_unexpected_size(KIND_SELECTIVE_ACK, 27); 446 447 expect_unexpected_size(KIND_SELECTIVE_ACK, 33); 448 expect_unexpected_size(KIND_SELECTIVE_ACK, 35); 449 450 expect_unexpected_size(KIND_TIMESTAMP, 9); 451 expect_unexpected_size(KIND_TIMESTAMP, 11); 452 } 453 } 454 } 455