1 use crate::err::{ipv6::SliceError, Layer, LenError}; 2 use crate::*; 3 4 /// Slice containing the IPv6 headers & payload. 5 #[derive(Clone, Debug, Eq, PartialEq)] 6 pub struct Ipv6Slice<'a> { 7 pub(crate) header: Ipv6HeaderSlice<'a>, 8 pub(crate) exts: Ipv6ExtensionsSlice<'a>, 9 pub(crate) payload: IpPayloadSlice<'a>, 10 } 11 12 impl<'a> Ipv6Slice<'a> { 13 /// Separates and validates IPv6 headers (including extension headers) 14 /// in the given slice and determine the sub-slice containing the payload 15 /// of the IPv6 packet (based on the payload length value in the header). 16 /// 17 /// Note that his function returns an [`crate::err::LenError`] if the given slice 18 /// contains less data then the `payload_len` field in the IPv6 header indicates 19 /// should be present. 20 /// 21 /// If you want to ignore these kind of length errors based on the length 22 /// fields in the IP headers use [`Ipv6Slice::from_slice_lax`] instead. from_slice(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError>23 pub fn from_slice(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError> { 24 // try reading the header 25 let header = Ipv6HeaderSlice::from_slice(slice).map_err(|err| { 26 use crate::err::ipv6::HeaderSliceError::*; 27 match err { 28 Len(err) => SliceError::Len(err), 29 Content(err) => SliceError::Header(err), 30 } 31 })?; 32 33 // restrict slice by the length specified in the header 34 let (header_payload, len_source) = 35 if 0 == header.payload_length() && slice.len() > Ipv6Header::LEN { 36 // In case the payload_length is 0 assume that the entire 37 // rest of the slice is part of the packet until the jumbogram 38 // parameters can be parsed. 39 40 // TODO: Add payload length parsing from the jumbogram 41 ( 42 unsafe { 43 core::slice::from_raw_parts( 44 slice.as_ptr().add(Ipv6Header::LEN), 45 slice.len() - Ipv6Header::LEN, 46 ) 47 }, 48 LenSource::Slice, 49 ) 50 } else { 51 let payload_len = usize::from(header.payload_length()); 52 let expected_len = Ipv6Header::LEN + payload_len; 53 if slice.len() < expected_len { 54 return Err(SliceError::Len(LenError { 55 required_len: expected_len, 56 len: slice.len(), 57 len_source: LenSource::Slice, 58 layer: Layer::Ipv6Packet, 59 layer_start_offset: 0, 60 })); 61 } else { 62 ( 63 unsafe { 64 core::slice::from_raw_parts( 65 slice.as_ptr().add(Ipv6Header::LEN), 66 payload_len, 67 ) 68 }, 69 LenSource::Ipv6HeaderPayloadLen, 70 ) 71 } 72 }; 73 74 // parse extension headers 75 let (exts, payload_ip_number, payload) = 76 Ipv6ExtensionsSlice::from_slice(header.next_header(), header_payload).map_err( 77 |err| { 78 // modify length errors 79 use crate::err::ipv6_exts::HeaderSliceError::*; 80 match err { 81 Len(mut err) => { 82 err.len_source = LenSource::Ipv6HeaderPayloadLen; 83 err.layer_start_offset += Ipv6Header::LEN; 84 SliceError::Len(err) 85 } 86 Content(err) => SliceError::Exts(err), 87 } 88 }, 89 )?; 90 91 let fragmented = exts.is_fragmenting_payload(); 92 Ok(Ipv6Slice { 93 header, 94 exts, 95 payload: IpPayloadSlice { 96 ip_number: payload_ip_number, 97 fragmented, 98 len_source, 99 payload, 100 }, 101 }) 102 } 103 104 /// Seperate an IPv6 header (+ extensions) & the payload from the given slice with 105 /// less strict length checks (useful for cut off packet or for packets with 106 /// unset length fields). 107 /// 108 /// If you want to only receive correct IpPayloads use [`crate::Ipv4Slice::from_slice`] 109 /// instead. 110 /// 111 /// The main usecases for this functions are: 112 /// 113 /// * Parsing packets that have been cut off. This is, for example, useful to 114 /// parse packets returned via ICMP as these usually only contain the start. 115 /// * Parsing packets where the `payload_length` (in the IPv6 header) has not 116 /// yet been set. This can be useful when parsing packets which have been 117 /// recorded in a layer before the length field was set (e.g. before the operating 118 /// system set the length fields). 119 /// 120 /// # Differences to `from_slice`: 121 /// 122 /// The main differences is that the function ignores inconsistent 123 /// `payload_length` values (in IPv6 headers). When these length values 124 /// in the IP header are inconsistant the length of the given slice is 125 /// used as a substitute. 126 /// 127 /// You can check if the slice length was used as a substitude by checking 128 /// if the `len_source` value in the returned [`IpPayloadSlice`] is set to 129 /// [`LenSource::Slice`]. If a substitution was not needed `len_source` 130 /// is set to [`LenSource::Ipv6HeaderPayloadLen`]. 131 /// 132 /// # When is the slice length used as a fallback? 133 /// 134 /// The slice length is used as a fallback/substitude if the `payload_length` 135 /// field in the IPv6 header is 136 /// 137 /// * Bigger then the given slice (payload cannot fully be seperated). 138 /// * The value `0`. from_slice_lax(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError>139 pub fn from_slice_lax(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError> { 140 // try reading the header 141 let header = Ipv6HeaderSlice::from_slice(slice).map_err(|err| { 142 use crate::err::ipv6::HeaderSliceError::*; 143 match err { 144 Len(err) => SliceError::Len(err), 145 Content(err) => SliceError::Header(err), 146 } 147 })?; 148 149 // restrict slice by the length specified in the header 150 let (header_payload, len_source) = 151 if 0 == header.payload_length() && slice.len() > Ipv6Header::LEN { 152 // In case the payload_length is 0 assume that the entire 153 // rest of the slice is part of the packet until the jumbogram 154 // parameters can be parsed. 155 156 // TODO: Add payload length parsing from the jumbogram 157 ( 158 unsafe { 159 core::slice::from_raw_parts( 160 slice.as_ptr().add(Ipv6Header::LEN), 161 slice.len() - Ipv6Header::LEN, 162 ) 163 }, 164 LenSource::Slice, 165 ) 166 } else { 167 let payload_len = usize::from(header.payload_length()); 168 let expected_len = Ipv6Header::LEN + payload_len; 169 if slice.len() < expected_len { 170 ( 171 unsafe { 172 core::slice::from_raw_parts( 173 slice.as_ptr().add(Ipv6Header::LEN), 174 slice.len() - Ipv6Header::LEN, 175 ) 176 }, 177 LenSource::Slice, 178 ) 179 } else { 180 ( 181 unsafe { 182 core::slice::from_raw_parts( 183 slice.as_ptr().add(Ipv6Header::LEN), 184 payload_len, 185 ) 186 }, 187 LenSource::Ipv6HeaderPayloadLen, 188 ) 189 } 190 }; 191 192 // parse extension headers 193 let (exts, payload_ip_number, payload) = 194 Ipv6ExtensionsSlice::from_slice(header.next_header(), header_payload).map_err( 195 |err| { 196 // modify length errors 197 use crate::err::ipv6_exts::HeaderSliceError::*; 198 match err { 199 Len(mut err) => { 200 err.len_source = len_source; 201 err.layer_start_offset += Ipv6Header::LEN; 202 SliceError::Len(err) 203 } 204 Content(err) => SliceError::Exts(err), 205 } 206 }, 207 )?; 208 209 let fragmented = exts.is_fragmenting_payload(); 210 Ok(Ipv6Slice { 211 header, 212 exts, 213 payload: IpPayloadSlice { 214 ip_number: payload_ip_number, 215 fragmented, 216 len_source, 217 payload, 218 }, 219 }) 220 } 221 222 /// Returns a slice containing the IPv6 header. 223 #[inline] header(&self) -> Ipv6HeaderSlice<'a>224 pub fn header(&self) -> Ipv6HeaderSlice<'a> { 225 self.header 226 } 227 228 /// Returns a slice containing the IPv6 extension headers. 229 #[inline] extensions(&self) -> &Ipv6ExtensionsSlice<'a>230 pub fn extensions(&self) -> &Ipv6ExtensionsSlice<'a> { 231 &self.exts 232 } 233 234 /// Returns a slice containing the data after the IPv6 header 235 /// and IPv6 extensions headers. 236 #[inline] payload(&self) -> &IpPayloadSlice<'a>237 pub fn payload(&self) -> &IpPayloadSlice<'a> { 238 &self.payload 239 } 240 241 /// Returns true if the payload is flagged as being fragmented. 242 #[inline] is_payload_fragmented(&self) -> bool243 pub fn is_payload_fragmented(&self) -> bool { 244 self.payload.fragmented 245 } 246 } 247 248 #[cfg(test)] 249 mod test { 250 use super::*; 251 use crate::{ 252 ip_number::{AUTH, IGMP, UDP}, 253 test_gens::*, 254 }; 255 use alloc::{format, vec::Vec}; 256 use proptest::prelude::*; 257 258 proptest! { 259 #[test] 260 fn debug_clone_eq( 261 ipv6_base in ipv6_any(), 262 auth_base in ip_auth_any() 263 ) { 264 let mut auth = auth_base.clone(); 265 auth.next_header = IGMP; 266 let payload: [u8;4] = [1,2,3,4]; 267 let mut data = Vec::with_capacity( 268 ipv6_base.header_len() + 269 auth.header_len() + 270 payload.len() 271 ); 272 let mut ipv6 = ipv6_base.clone(); 273 ipv6.next_header = AUTH; 274 ipv6.payload_length = (auth.header_len() + payload.len()) as u16; 275 data.extend_from_slice(&ipv6.to_bytes()); 276 data.extend_from_slice(&auth.to_bytes()); 277 data.extend_from_slice(&payload); 278 279 // decode packet 280 let slice = Ipv6Slice::from_slice(&data).unwrap(); 281 282 // check debug output 283 prop_assert_eq!( 284 format!("{:?}", slice), 285 format!( 286 "Ipv6Slice {{ header: {:?}, exts: {:?}, payload: {:?} }}", 287 slice.header(), 288 slice.extensions(), 289 slice.payload() 290 ) 291 ); 292 prop_assert_eq!(slice.clone(), slice); 293 } 294 } 295 296 proptest! { 297 #[test] 298 fn from_slice( 299 ipv6_base in ipv6_any(), 300 auth_base in ip_auth_any() 301 ) { 302 let payload: [u8;6] = [1,2,3,4,5,6]; 303 304 // build packets 305 let data_without_ext = { 306 let mut data = Vec::with_capacity( 307 ipv6_base.header_len() + 308 payload.len() + 309 4 310 ); 311 let mut ipv6 = ipv6_base.clone(); 312 ipv6.payload_length = (payload.len()) as u16; 313 ipv6.next_header = UDP; 314 data.extend_from_slice(&ipv6.to_bytes()); 315 data.extend_from_slice(&payload); 316 data.extend_from_slice(&[0,0,0,0]); 317 data 318 }; 319 let data_with_ext = { 320 let payload: [u8;6] = [1,2,3,4,5,6]; 321 let mut data = Vec::with_capacity( 322 ipv6_base.header_len() + 323 auth_base.header_len() + 324 payload.len() + 325 4 326 ); 327 let mut ipv6 = ipv6_base.clone(); 328 ipv6.payload_length = (auth_base.header_len() + payload.len()) as u16; 329 ipv6.next_header = AUTH; 330 let mut auth = auth_base.clone(); 331 auth.next_header = UDP; 332 data.extend_from_slice(&ipv6.to_bytes()); 333 data.extend_from_slice(&auth.to_bytes()); 334 data.extend_from_slice(&payload); 335 data.extend_from_slice(&[0,0,0,0]); 336 data 337 }; 338 339 // parsing without extensions (normal length) 340 { 341 let actual = Ipv6Slice::from_slice(&data_without_ext).unwrap(); 342 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]); 343 prop_assert!(actual.extensions().first_header().is_none()); 344 prop_assert_eq!( 345 actual.payload(), 346 &IpPayloadSlice{ 347 ip_number: UDP.into(), 348 fragmented: false, 349 len_source: LenSource::Ipv6HeaderPayloadLen, 350 payload: &payload, 351 } 352 ); 353 } 354 355 // parsing with extensions (normal length) 356 { 357 let actual = Ipv6Slice::from_slice(&data_with_ext).unwrap(); 358 prop_assert_eq!(actual.header().slice(), &data_with_ext[..ipv6_base.header_len()]); 359 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data_with_ext[ipv6_base.header_len()..]).unwrap(); 360 prop_assert_eq!( 361 actual.extensions(), 362 &expected 363 ); 364 prop_assert_eq!( 365 actual.payload(), 366 &IpPayloadSlice{ 367 ip_number: UDP.into(), 368 fragmented: false, 369 len_source: LenSource::Ipv6HeaderPayloadLen, 370 payload: &payload, 371 } 372 ); 373 } 374 375 // parsing without extensions (zero length, fallback to slice length) 376 { 377 // inject zero as payload length 378 let mut data = data_without_ext.clone(); 379 data[4] = 0; 380 data[5] = 0; 381 let actual = Ipv6Slice::from_slice(&data).unwrap(); 382 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]); 383 prop_assert!(actual.extensions().first_header().is_none()); 384 prop_assert_eq!( 385 actual.payload(), 386 &IpPayloadSlice{ 387 ip_number: UDP.into(), 388 fragmented: false, 389 len_source: LenSource::Slice, 390 payload: &data[ipv6_base.header_len()..], 391 } 392 ); 393 } 394 395 // parsing with extensions (zero length, fallback to slice length) 396 { 397 // inject zero as payload length 398 let mut data = data_with_ext.clone(); 399 data[4] = 0; 400 data[5] = 0; 401 let actual = Ipv6Slice::from_slice(&data).unwrap(); 402 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]); 403 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data[ipv6_base.header_len()..]).unwrap(); 404 prop_assert_eq!( 405 actual.extensions(), 406 &expected 407 ); 408 prop_assert_eq!( 409 actual.payload(), 410 &IpPayloadSlice{ 411 ip_number: UDP.into(), 412 fragmented: false, 413 len_source: LenSource::Slice, 414 payload: &data[ipv6_base.header_len() + auth_base.header_len()..], 415 } 416 ); 417 } 418 419 // header content error 420 { 421 use crate::err::ipv6::HeaderError; 422 // inject invalid ip version 423 let mut data = data_without_ext.clone(); 424 data[0] = data[0] & 0x0f; // version 0 425 prop_assert_eq!( 426 Ipv6Slice::from_slice(&data).unwrap_err(), 427 SliceError::Header( 428 HeaderError::UnexpectedVersion{ version_number: 0 } 429 ) 430 ); 431 } 432 433 // header length error 434 for len in 0..Ipv6Header::LEN { 435 prop_assert_eq!( 436 Ipv6Slice::from_slice(&data_without_ext[..len]).unwrap_err(), 437 SliceError::Len( 438 LenError{ 439 required_len: Ipv6Header::LEN, 440 len, 441 len_source: LenSource::Slice, 442 layer: Layer::Ipv6Header, 443 layer_start_offset: 0 444 } 445 ) 446 ); 447 } 448 449 // payload length error without auth header 450 { 451 use crate::err::{LenError, Layer}; 452 453 let required_len = ipv6_base.header_len() + payload.len(); 454 prop_assert_eq!( 455 Ipv6Slice::from_slice(&data_without_ext[..required_len - 1]).unwrap_err(), 456 SliceError::Len(LenError{ 457 required_len: required_len, 458 len: required_len - 1, 459 len_source: LenSource::Slice, 460 layer: Layer::Ipv6Packet, 461 layer_start_offset: 0, 462 }) 463 ); 464 } 465 466 // payload length error auth header 467 { 468 use crate::err::{LenError, Layer}; 469 470 let required_len = ipv6_base.header_len() + auth_base.header_len() + payload.len(); 471 prop_assert_eq!( 472 Ipv6Slice::from_slice(&data_with_ext[..required_len - 1]).unwrap_err(), 473 SliceError::Len(LenError{ 474 required_len: required_len, 475 len: required_len - 1, 476 len_source: LenSource::Slice, 477 layer: Layer::Ipv6Packet, 478 layer_start_offset: 0, 479 }) 480 ); 481 } 482 483 // auth length error 484 { 485 use crate::err::{LenError, Layer}; 486 487 // inject payload length that is smaller then the auth header 488 let mut data = data_with_ext.clone(); 489 let payload_len_too_small = auth_base.header_len() - 1; 490 { 491 let plts = (payload_len_too_small as u16).to_be_bytes(); 492 data[4] = plts[0]; 493 data[5] = plts[1]; 494 } 495 496 prop_assert_eq!( 497 Ipv6Slice::from_slice(&data).unwrap_err(), 498 SliceError::Len( 499 LenError{ 500 required_len: auth_base.header_len(), 501 len: auth_base.header_len() - 1, 502 len_source: LenSource::Ipv6HeaderPayloadLen, 503 layer: Layer::IpAuthHeader, 504 layer_start_offset: ipv6_base.header_len(), 505 } 506 ) 507 ); 508 } 509 510 // auth content error 511 { 512 use crate::err::{ip_auth, ipv6_exts}; 513 514 // inject zero as auth header length 515 let mut data = data_with_ext.clone(); 516 data[ipv6_base.header_len() + 1] = 0; 517 518 prop_assert_eq!( 519 Ipv6Slice::from_slice(&data).unwrap_err(), 520 SliceError::Exts(ipv6_exts::HeaderError::IpAuth( 521 ip_auth::HeaderError::ZeroPayloadLen 522 )) 523 ); 524 } 525 } 526 } 527 528 proptest! { 529 #[test] 530 fn from_slice_lax( 531 ipv6_base in ipv6_any(), 532 auth_base in ip_auth_any() 533 ) { 534 let payload: [u8;6] = [1,2,3,4,5,6]; 535 536 // build packets 537 let data_without_ext = { 538 let mut data = Vec::with_capacity( 539 ipv6_base.header_len() + 540 payload.len() + 541 4 542 ); 543 let mut ipv6 = ipv6_base.clone(); 544 ipv6.payload_length = (payload.len()) as u16; 545 ipv6.next_header = UDP; 546 data.extend_from_slice(&ipv6.to_bytes()); 547 data.extend_from_slice(&payload); 548 data.extend_from_slice(&[0,0,0,0]); 549 data 550 }; 551 let data_with_ext = { 552 let payload: [u8;6] = [1,2,3,4,5,6]; 553 let mut data = Vec::with_capacity( 554 ipv6_base.header_len() + 555 auth_base.header_len() + 556 payload.len() + 557 4 558 ); 559 let mut ipv6 = ipv6_base.clone(); 560 ipv6.payload_length = (auth_base.header_len() + payload.len()) as u16; 561 ipv6.next_header = AUTH; 562 let mut auth = auth_base.clone(); 563 auth.next_header = UDP; 564 data.extend_from_slice(&ipv6.to_bytes()); 565 data.extend_from_slice(&auth.to_bytes()); 566 data.extend_from_slice(&payload); 567 data.extend_from_slice(&[0,0,0,0]); 568 data 569 }; 570 571 // parsing without extensions (normal length) 572 { 573 let actual = Ipv6Slice::from_slice_lax(&data_without_ext).unwrap(); 574 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]); 575 prop_assert!(actual.extensions().first_header().is_none()); 576 prop_assert_eq!( 577 actual.payload(), 578 &IpPayloadSlice{ 579 ip_number: UDP.into(), 580 fragmented: false, 581 len_source: LenSource::Ipv6HeaderPayloadLen, 582 payload: &payload, 583 } 584 ); 585 } 586 587 // parsing with extensions (normal length) 588 { 589 let actual = Ipv6Slice::from_slice_lax(&data_with_ext).unwrap(); 590 prop_assert_eq!(actual.header().slice(), &data_with_ext[..ipv6_base.header_len()]); 591 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data_with_ext[ipv6_base.header_len()..]).unwrap(); 592 prop_assert_eq!( 593 actual.extensions(), 594 &expected 595 ); 596 prop_assert_eq!( 597 actual.payload(), 598 &IpPayloadSlice{ 599 ip_number: UDP.into(), 600 fragmented: false, 601 len_source: LenSource::Ipv6HeaderPayloadLen, 602 payload: &payload, 603 } 604 ); 605 } 606 607 // parsing without extensions (zero length, fallback to slice length) 608 { 609 // inject zero as payload length 610 let mut data = data_without_ext.clone(); 611 data[4] = 0; 612 data[5] = 0; 613 let actual = Ipv6Slice::from_slice_lax(&data).unwrap(); 614 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]); 615 prop_assert!(actual.extensions().first_header().is_none()); 616 prop_assert_eq!( 617 actual.payload(), 618 &IpPayloadSlice{ 619 ip_number: UDP.into(), 620 fragmented: false, 621 len_source: LenSource::Slice, 622 payload: &data[ipv6_base.header_len()..], 623 } 624 ); 625 } 626 627 // parsing with extensions (zero length, fallback to slice length) 628 { 629 // inject zero as payload length 630 let mut data = data_with_ext.clone(); 631 data[4] = 0; 632 data[5] = 0; 633 let actual = Ipv6Slice::from_slice_lax(&data).unwrap(); 634 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]); 635 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data[ipv6_base.header_len()..]).unwrap(); 636 prop_assert_eq!( 637 actual.extensions(), 638 &expected 639 ); 640 prop_assert_eq!( 641 actual.payload(), 642 &IpPayloadSlice{ 643 ip_number: UDP.into(), 644 fragmented: false, 645 len_source: LenSource::Slice, 646 payload: &data[ipv6_base.header_len() + auth_base.header_len()..], 647 } 648 ); 649 } 650 651 // header content error 652 { 653 use crate::err::ipv6::HeaderError; 654 // inject invalid ip version 655 let mut data = data_without_ext.clone(); 656 data[0] = data[0] & 0x0f; // version 0 657 prop_assert_eq!( 658 Ipv6Slice::from_slice_lax(&data).unwrap_err(), 659 SliceError::Header( 660 HeaderError::UnexpectedVersion{ version_number: 0 } 661 ) 662 ); 663 } 664 665 // header length error 666 for len in 0..Ipv6Header::LEN { 667 prop_assert_eq!( 668 Ipv6Slice::from_slice_lax(&data_without_ext[..len]).unwrap_err(), 669 SliceError::Len( 670 LenError{ 671 required_len: Ipv6Header::LEN, 672 len, 673 len_source: LenSource::Slice, 674 layer: Layer::Ipv6Header, 675 layer_start_offset: 0 676 } 677 ) 678 ); 679 } 680 681 // payload length larger then slice (fallback to slice length) 682 { 683 let len = ipv6_base.header_len() + payload.len() - 1; 684 let actual = Ipv6Slice::from_slice_lax(&data_without_ext[..len]).unwrap(); 685 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]); 686 prop_assert_eq!( 687 0, 688 actual.extensions().slice().len() 689 ); 690 prop_assert_eq!( 691 actual.payload(), 692 &IpPayloadSlice{ 693 ip_number: UDP.into(), 694 fragmented: false, 695 len_source: LenSource::Slice, 696 payload: &data_without_ext[ipv6_base.header_len()..len], 697 } 698 ); 699 } 700 701 // payload length error auth header 702 { 703 use crate::err::{LenError, Layer}; 704 705 let required_len = ipv6_base.header_len() + auth_base.header_len(); 706 prop_assert_eq!( 707 Ipv6Slice::from_slice_lax(&data_with_ext[..required_len - 1]).unwrap_err(), 708 SliceError::Len(LenError{ 709 required_len: required_len - Ipv6Header::LEN, 710 len: required_len - Ipv6Header::LEN - 1, 711 len_source: LenSource::Slice, 712 layer: Layer::IpAuthHeader, 713 layer_start_offset: Ipv6Header::LEN, 714 }) 715 ); 716 } 717 718 // auth length error 719 { 720 use crate::err::{LenError, Layer}; 721 722 // inject payload length that is smaller then the auth header 723 let mut data = data_with_ext.clone(); 724 let payload_len_too_small = auth_base.header_len() - 1; 725 { 726 let plts = (payload_len_too_small as u16).to_be_bytes(); 727 data[4] = plts[0]; 728 data[5] = plts[1]; 729 } 730 731 prop_assert_eq!( 732 Ipv6Slice::from_slice_lax(&data).unwrap_err(), 733 SliceError::Len( 734 LenError{ 735 required_len: auth_base.header_len(), 736 len: auth_base.header_len() - 1, 737 len_source: LenSource::Ipv6HeaderPayloadLen, 738 layer: Layer::IpAuthHeader, 739 layer_start_offset: ipv6_base.header_len(), 740 } 741 ) 742 ); 743 } 744 745 // auth content error 746 { 747 use crate::err::{ip_auth, ipv6_exts}; 748 749 // inject zero as auth header length 750 let mut data = data_with_ext.clone(); 751 data[ipv6_base.header_len() + 1] = 0; 752 753 prop_assert_eq!( 754 Ipv6Slice::from_slice_lax(&data).unwrap_err(), 755 SliceError::Exts(ipv6_exts::HeaderError::IpAuth( 756 ip_auth::HeaderError::ZeroPayloadLen 757 )) 758 ); 759 } 760 } 761 } 762 763 #[test] is_payload_fragmented()764 fn is_payload_fragmented() { 765 use crate::ip_number::{IPV6_FRAG, UDP}; 766 767 // not fragmented 768 { 769 let data = Ipv6Header { 770 traffic_class: 0, 771 flow_label: 1.try_into().unwrap(), 772 payload_length: 0, 773 next_header: UDP, 774 hop_limit: 4, 775 source: [0; 16], 776 destination: [0; 16], 777 } 778 .to_bytes(); 779 assert_eq!( 780 false, 781 Ipv6Slice::from_slice(&data) 782 .unwrap() 783 .is_payload_fragmented() 784 ); 785 } 786 787 // fragmented 788 { 789 let ipv6_frag = Ipv6FragmentHeader { 790 next_header: UDP, 791 fragment_offset: 0.try_into().unwrap(), 792 more_fragments: true, 793 identification: 0, 794 }; 795 let ipv6 = Ipv6Header { 796 traffic_class: 0, 797 flow_label: 1.try_into().unwrap(), 798 payload_length: ipv6_frag.header_len() as u16, 799 next_header: IPV6_FRAG, 800 hop_limit: 4, 801 source: [0; 16], 802 destination: [0; 16], 803 }; 804 805 let mut data = Vec::with_capacity(ipv6.header_len() + ipv6_frag.header_len()); 806 data.extend_from_slice(&ipv6.to_bytes()); 807 data.extend_from_slice(&ipv6_frag.to_bytes()); 808 assert!(Ipv6Slice::from_slice(&data) 809 .unwrap() 810 .is_payload_fragmented()); 811 } 812 } 813 } 814