1 #[cfg(feature = "std")] 2 use crate::err::ip::HeadersWriteError; 3 use crate::err::{Layer, LenError, ValueTooBigError}; 4 use crate::*; 5 6 /// Internet protocol headers version 4 & 6. 7 #[derive(Clone, Debug, Eq, PartialEq)] 8 #[allow(clippy::large_enum_variant)] 9 pub enum IpHeaders { 10 /// IPv4 header & extension headers. 11 Ipv4(Ipv4Header, Ipv4Extensions), 12 /// IPv6 header & extension headers. 13 Ipv6(Ipv6Header, Ipv6Extensions), 14 } 15 16 impl IpHeaders { 17 /// Maximum summed up length of all extension headers in bytes/octets. 18 pub const MAX_LEN: usize = Ipv6Header::LEN + Ipv6Extensions::MAX_LEN; 19 20 /// Returns references to the IPv4 header & extensions if the header contains IPv4 values. ipv4(&self) -> Option<(&Ipv4Header, &Ipv4Extensions)>21 pub fn ipv4(&self) -> Option<(&Ipv4Header, &Ipv4Extensions)> { 22 if let IpHeaders::Ipv4(header, exts) = self { 23 Some((header, exts)) 24 } else { 25 None 26 } 27 } 28 29 /// Returns references to the IPv6 header & extensions if the header contains IPv6 values. ipv6(&self) -> Option<(&Ipv6Header, &Ipv6Extensions)>30 pub fn ipv6(&self) -> Option<(&Ipv6Header, &Ipv6Extensions)> { 31 if let IpHeaders::Ipv6(header, exts) = self { 32 Some((header, exts)) 33 } else { 34 None 35 } 36 } 37 38 /// Renamed to [`IpHeaders::from_slice`] 39 #[deprecated(since = "0.10.1", note = "Renamed to `IpHeaders::from_slice`")] 40 #[inline] read_from_slice( slice: &[u8], ) -> Result<(IpHeaders, IpNumber, &[u8]), err::ip::HeadersSliceError>41 pub fn read_from_slice( 42 slice: &[u8], 43 ) -> Result<(IpHeaders, IpNumber, &[u8]), err::ip::HeadersSliceError> { 44 let (header, payload) = IpHeaders::from_slice(slice)?; 45 Ok((header, payload.ip_number, payload.payload)) 46 } 47 48 /// Read an [`IpHeaders`] from a slice and return the headers & payload of 49 /// the IP packet (determined based on the length fields in the IP header). 50 /// 51 /// Note that his function returns an [`crate::err::LenError`] if the given slice 52 /// contains less data then the length fields in the IP header indicate should 53 /// be present. 54 /// 55 /// If you want to ignore these kind of length errors based on the length 56 /// fields in the IP headers use [`IpHeaders::from_slice_lax`] instead. from_slice( slice: &[u8], ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ip::HeadersSliceError>57 pub fn from_slice( 58 slice: &[u8], 59 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ip::HeadersSliceError> { 60 use err::ip::{HeaderError::*, HeadersError::*, HeadersSliceError::*}; 61 62 if slice.is_empty() { 63 Err(Len(err::LenError { 64 required_len: 1, 65 len: slice.len(), 66 len_source: LenSource::Slice, 67 layer: err::Layer::IpHeader, 68 layer_start_offset: 0, 69 })) 70 } else { 71 match slice[0] >> 4 { 72 4 => { 73 // check length 74 if slice.len() < Ipv4Header::MIN_LEN { 75 return Err(Len(err::LenError { 76 required_len: Ipv4Header::MIN_LEN, 77 len: slice.len(), 78 len_source: LenSource::Slice, 79 layer: err::Layer::Ipv4Header, 80 layer_start_offset: 0, 81 })); 82 } 83 84 // read ihl 85 // 86 // SAFETY: 87 // Safe as the slice length is checked to be at least 88 // Ipv4Header::MIN_LEN (20) at the start. 89 let ihl = unsafe { slice.get_unchecked(0) } & 0xf; 90 91 //check that the ihl is correct 92 if ihl < 5 { 93 return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl }))); 94 } 95 96 // check that the slice contains enough data for the entire header + options 97 let header_len = usize::from(ihl) * 4; 98 if slice.len() < header_len { 99 return Err(Len(LenError { 100 required_len: header_len, 101 len: slice.len(), 102 len_source: LenSource::Slice, 103 layer: Layer::Ipv4Header, 104 layer_start_offset: 0, 105 })); 106 } 107 108 let header = unsafe { 109 // SAFETY: Safe as the IHL & slice len has been validated 110 Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts( 111 slice.as_ptr(), 112 header_len, 113 )) 114 .to_header() 115 }; 116 117 // check that the total len is at least containing the header len 118 let total_len: usize = header.total_len.into(); 119 if total_len < header_len { 120 return Err(Len(LenError { 121 required_len: header_len, 122 len: total_len, 123 len_source: LenSource::Ipv4HeaderTotalLen, 124 layer: Layer::Ipv4Packet, 125 layer_start_offset: 0, 126 })); 127 } 128 129 // restrict the rest of the slice based on the total len 130 let rest = if slice.len() < total_len { 131 return Err(Len(LenError { 132 required_len: total_len, 133 len: slice.len(), 134 len_source: LenSource::Slice, 135 layer: Layer::Ipv4Packet, 136 layer_start_offset: 0, 137 })); 138 } else { 139 unsafe { 140 core::slice::from_raw_parts( 141 // SAFETY: Safe as the slice length was validated to be at least header_length 142 slice.as_ptr().add(header_len), 143 // SAFETY: Safe as slice length has been validated to be at least total_length_usize long 144 total_len - header_len, 145 ) 146 } 147 }; 148 149 let (exts, next_protocol, rest) = 150 Ipv4Extensions::from_slice(header.protocol, rest).map_err(|err| { 151 use err::ip_auth::HeaderSliceError as I; 152 match err { 153 I::Len(mut err) => { 154 err.layer_start_offset += header_len; 155 err.len_source = LenSource::Ipv4HeaderTotalLen; 156 Len(err) 157 } 158 I::Content(err) => Content(Ipv4Ext(err)), 159 } 160 })?; 161 162 let fragmented = header.is_fragmenting_payload(); 163 Ok(( 164 IpHeaders::Ipv4(header, exts), 165 IpPayloadSlice { 166 ip_number: next_protocol, 167 fragmented, 168 len_source: LenSource::Ipv4HeaderTotalLen, 169 payload: rest, 170 }, 171 )) 172 } 173 6 => { 174 if slice.len() < Ipv6Header::LEN { 175 return Err(Len(err::LenError { 176 required_len: Ipv6Header::LEN, 177 len: slice.len(), 178 len_source: LenSource::Slice, 179 layer: err::Layer::Ipv6Header, 180 layer_start_offset: 0, 181 })); 182 } 183 let header = { 184 // SAFETY: 185 // This is safe as the slice length is checked to be 186 // at least Ipv6Header::LEN (40) before this code block. 187 unsafe { 188 Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts( 189 slice.as_ptr(), 190 Ipv6Header::LEN, 191 )) 192 .to_header() 193 } 194 }; 195 196 // restrict slice by the length specified in the header 197 let (header_payload, len_source) = 198 if 0 == header.payload_length && slice.len() > Ipv6Header::LEN { 199 // In case the payload_length is 0 assume that the entire 200 // rest of the slice is part of the packet until the jumbogram 201 // parameters can be parsed. 202 203 // TODO: Add payload length parsing from the jumbogram 204 unsafe { 205 ( 206 core::slice::from_raw_parts( 207 slice.as_ptr().add(Ipv6Header::LEN), 208 slice.len() - Ipv6Header::LEN, 209 ), 210 LenSource::Slice, 211 ) 212 } 213 } else { 214 let payload_len: usize = header.payload_length.into(); 215 let expected_len = Ipv6Header::LEN + payload_len; 216 if slice.len() < expected_len { 217 return Err(Len(LenError { 218 required_len: expected_len, 219 len: slice.len(), 220 len_source: LenSource::Slice, 221 layer: Layer::Ipv6Packet, 222 layer_start_offset: 0, 223 })); 224 } else { 225 unsafe { 226 ( 227 core::slice::from_raw_parts( 228 slice.as_ptr().add(Ipv6Header::LEN), 229 payload_len, 230 ), 231 LenSource::Ipv6HeaderPayloadLen, 232 ) 233 } 234 } 235 }; 236 237 let (exts, next_header, rest) = 238 Ipv6Extensions::from_slice(header.next_header, header_payload).map_err( 239 |err| { 240 use err::ipv6_exts::HeaderSliceError as I; 241 match err { 242 I::Len(mut err) => { 243 err.layer_start_offset += Ipv6Header::LEN; 244 err.len_source = len_source; 245 Len(err) 246 } 247 I::Content(err) => Content(Ipv6Ext(err)), 248 } 249 }, 250 )?; 251 252 let fragmented = exts.is_fragmenting_payload(); 253 Ok(( 254 IpHeaders::Ipv6(header, exts), 255 IpPayloadSlice { 256 ip_number: next_header, 257 fragmented, 258 len_source, 259 payload: rest, 260 }, 261 )) 262 } 263 version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))), 264 } 265 } 266 } 267 268 /// Reads an [`IpHeaders`] as far as possible without encountering an error & 269 /// separates the payload from the given slice with less strict length checks. 270 /// This function is usefull for cut off packet or for packets with unset length 271 /// fields). 272 /// 273 /// If you want to only receive correct IpPayloads use [`IpHeaders::from_slice`] 274 /// instead. 275 /// 276 /// The main usecases for this functions are: 277 /// 278 /// * Parsing packets that have been cut off. This is, for example, useful to 279 /// parse packets returned via ICMP as these usually only contain the start. 280 /// * Parsing packets where the `total_len` (for IPv4) or `payload_length` (for IPv6) 281 /// have not yet been set. This can be useful when parsing packets which have been 282 /// recorded in a layer before the length field was set (e.g. before the operating 283 /// system set the length fields). 284 /// 285 /// # Differences to `from_slice`: 286 /// 287 /// There are two main differences: 288 /// 289 /// * Errors in the expansion headers will only stop the parsing and return an `Ok` 290 /// with the successfully parsed parts and the error as optional. Only if an 291 /// unrecoverable error is encountered in the IP header itself an `Err` is returned. 292 /// In the normal `from_slice` function an `Err` is returned if an error is 293 /// encountered in an exteions header. 294 /// * `from_slice_lax` ignores inconsistent `total_len` (in IPv4 headers) and 295 /// inconsistent `payload_length` (in IPv6 headers) values. When these length 296 /// values in the IP header are inconsistant the length of the given slice is 297 /// used as a substitute. 298 /// 299 /// You can check if the slice length was used as a substitude by checking 300 /// if the `len_source` value in the returned [`LaxIpPayloadSlice`] is set to 301 /// [`LenSource::Slice`]. If a substitution was not needed `len_source` 302 /// is set to [`LenSource::Ipv4HeaderTotalLen`] or 303 /// [`LenSource::Ipv6HeaderPayloadLen`]. 304 /// 305 /// # When is the slice length used as a fallback? 306 /// 307 /// For IPv4 packets the slice length is used as a fallback/substitude 308 /// if the `total_length` field in the IPv4 header is: 309 /// 310 /// * Bigger then the given slice (payload cannot fully be seperated). 311 /// * Too small to contain at least the IPv4 header. 312 /// 313 /// For IPv6 packet the slice length is used as a fallback/substitude 314 /// if the `payload_length` is 315 /// 316 /// * Bigger then the given slice (payload cannot fully be seperated). 317 /// * The value `0`. from_slice_lax( slice: &[u8], ) -> Result< ( IpHeaders, LaxIpPayloadSlice<'_>, Option<(err::ip_exts::HeadersSliceError, Layer)>, ), err::ip::LaxHeaderSliceError, >318 pub fn from_slice_lax( 319 slice: &[u8], 320 ) -> Result< 321 ( 322 IpHeaders, 323 LaxIpPayloadSlice<'_>, 324 Option<(err::ip_exts::HeadersSliceError, Layer)>, 325 ), 326 err::ip::LaxHeaderSliceError, 327 > { 328 use err::ip::{HeaderError::*, LaxHeaderSliceError::*}; 329 330 if slice.is_empty() { 331 Err(Len(err::LenError { 332 required_len: 1, 333 len: slice.len(), 334 len_source: LenSource::Slice, 335 layer: err::Layer::IpHeader, 336 layer_start_offset: 0, 337 })) 338 } else { 339 match slice[0] >> 4 { 340 4 => { 341 // check length 342 if slice.len() < Ipv4Header::MIN_LEN { 343 return Err(Len(err::LenError { 344 required_len: Ipv4Header::MIN_LEN, 345 len: slice.len(), 346 len_source: LenSource::Slice, 347 layer: err::Layer::Ipv4Header, 348 layer_start_offset: 0, 349 })); 350 } 351 352 // read ihl 353 // 354 // SAFETY: 355 // Safe as the slice length is checked to be at least 356 // Ipv4Header::MIN_LEN (20) at the start. 357 let ihl = unsafe { slice.get_unchecked(0) } & 0xf; 358 359 //check that the ihl is correct 360 if ihl < 5 { 361 return Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl })); 362 } 363 364 // check that the slice contains enough data for the entire header + options 365 let header_len = usize::from(ihl) * 4; 366 if slice.len() < header_len { 367 return Err(Len(LenError { 368 required_len: header_len, 369 len: slice.len(), 370 len_source: LenSource::Slice, 371 layer: Layer::Ipv4Header, 372 layer_start_offset: 0, 373 })); 374 } 375 376 let header = unsafe { 377 // SAFETY: Safe as the IHL & slice len has been validated 378 Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts( 379 slice.as_ptr(), 380 header_len, 381 )) 382 .to_header() 383 }; 384 385 // check that the total len is at least containing the header len 386 let total_len: usize = header.total_len.into(); 387 388 // restrict the rest of the slice based on the total len (if the total_len is not conflicting) 389 let (len_source, rest, incomplete) = if total_len < header_len { 390 // fallback to slice len 391 ( 392 LenSource::Slice, 393 unsafe { 394 core::slice::from_raw_parts( 395 // SAFETY: Safe as the slice length was validated to be at least header_length 396 slice.as_ptr().add(header_len), 397 // SAFETY: Safe as slice length has been validated to be at least header_len long 398 slice.len() - header_len, 399 ) 400 }, 401 false, 402 ) 403 } else if slice.len() < total_len { 404 ( 405 LenSource::Slice, 406 unsafe { 407 core::slice::from_raw_parts( 408 // SAFETY: Safe as the slice length was validated to be at least header_length 409 slice.as_ptr().add(header_len), 410 // SAFETY: Safe as slice length has been validated to be at least header_len long 411 slice.len() - header_len, 412 ) 413 }, 414 true, 415 ) 416 } else { 417 ( 418 LenSource::Ipv4HeaderTotalLen, 419 unsafe { 420 core::slice::from_raw_parts( 421 // SAFETY: Safe as the slice length was validated to be at least header_length 422 slice.as_ptr().add(header_len), 423 // SAFETY: Safe as slice length has been validated to be at least total_length_usize long 424 total_len - header_len, 425 ) 426 }, 427 false, 428 ) 429 }; 430 431 let (exts, next_protocol, rest, stop_err) = 432 Ipv4Extensions::from_slice_lax(header.protocol, rest); 433 434 let stop_err = stop_err.map(|err| { 435 use err::ip_auth::HeaderSliceError as I; 436 use err::ip_exts::HeaderError as OC; 437 use err::ip_exts::HeadersSliceError as O; 438 match err { 439 I::Len(mut l) => O::Len({ 440 l.layer_start_offset += header_len; 441 l.len_source = len_source; 442 l 443 }), 444 I::Content(c) => O::Content(OC::Ipv4Ext(c)), 445 } 446 }); 447 448 let fragmented = header.is_fragmenting_payload(); 449 Ok(( 450 IpHeaders::Ipv4(header, exts), 451 LaxIpPayloadSlice { 452 incomplete, 453 ip_number: next_protocol, 454 fragmented, 455 len_source, 456 payload: rest, 457 }, 458 stop_err.map(|v| (v, Layer::IpAuthHeader)), 459 )) 460 } 461 6 => { 462 if slice.len() < Ipv6Header::LEN { 463 return Err(Len(err::LenError { 464 required_len: Ipv6Header::LEN, 465 len: slice.len(), 466 len_source: LenSource::Slice, 467 layer: err::Layer::Ipv6Header, 468 layer_start_offset: 0, 469 })); 470 } 471 let header = { 472 // SAFETY: 473 // This is safe as the slice length is checked to be 474 // at least Ipv6Header::LEN (40) befpre this code block. 475 unsafe { 476 Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts( 477 slice.as_ptr(), 478 Ipv6Header::LEN, 479 )) 480 .to_header() 481 } 482 }; 483 484 // restrict slice by the length specified in the header 485 let payload_len = usize::from(header.payload_length); 486 let (header_payload, len_source, incomplete) = 487 if (header.payload_length == 0) && (Ipv6Header::LEN < slice.len()) { 488 // TODO: Add payload length parsing from the jumbogram 489 unsafe { 490 ( 491 core::slice::from_raw_parts( 492 // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above. 493 slice.as_ptr().add(Ipv6Header::LEN), 494 // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above. 495 slice.len() - Ipv6Header::LEN, 496 ), 497 LenSource::Slice, 498 false, 499 ) 500 } 501 } else if (slice.len() - Ipv6Header::LEN) < payload_len { 502 unsafe { 503 ( 504 core::slice::from_raw_parts( 505 // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above. 506 slice.as_ptr().add(Ipv6Header::LEN), 507 // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above. 508 slice.len() - Ipv6Header::LEN, 509 ), 510 LenSource::Slice, 511 true, 512 ) 513 } 514 } else { 515 unsafe { 516 ( 517 core::slice::from_raw_parts( 518 // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above. 519 slice.as_ptr().add(Ipv6Header::LEN), 520 // SAFTEY: Safe as we verify that `(slice.len() - Ipv6Header::LEN) >= payload_len` above. 521 payload_len, 522 ), 523 LenSource::Ipv6HeaderPayloadLen, 524 false, 525 ) 526 } 527 }; 528 529 let (exts, next_header, rest, stop_err) = 530 Ipv6Extensions::from_slice_lax(header.next_header, header_payload); 531 532 let stop_err = stop_err.map(|(err, layer)| { 533 use err::ip_exts::HeaderError::Ipv6Ext; 534 use err::ip_exts::HeadersSliceError as O; 535 use err::ipv6_exts::HeaderSliceError as I; 536 ( 537 match err { 538 I::Len(mut l) => { 539 l.layer_start_offset += Ipv6Header::LEN; 540 l.len_source = len_source; 541 O::Len(l) 542 } 543 I::Content(c) => O::Content(Ipv6Ext(c)), 544 }, 545 layer, 546 ) 547 }); 548 549 let fragmented = exts.is_fragmenting_payload(); 550 Ok(( 551 IpHeaders::Ipv6(header, exts), 552 LaxIpPayloadSlice { 553 incomplete, 554 ip_number: next_header, 555 fragmented, 556 len_source, 557 payload: rest, 558 }, 559 stop_err, 560 )) 561 } 562 version_number => Err(Content(UnsupportedIpVersion { version_number })), 563 } 564 } 565 } 566 567 /// Read an IPv4 header & extension headers from a slice and return the slice containing the payload 568 /// according to the total_length field in the IPv4 header. 569 /// 570 /// Note that his function returns an [`err::LenError`] if the given slice 571 /// contains less data then the `total_len` field in the IPv4 header indicates 572 /// should be present. 573 /// 574 /// If you want to ignore these kind of length errors based on the length 575 /// fields in the IP headers use [`IpHeaders::from_ipv4_slice_lax`] instead. from_ipv4_slice( slice: &[u8], ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv4::SliceError>576 pub fn from_ipv4_slice( 577 slice: &[u8], 578 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv4::SliceError> { 579 use err::ipv4::SliceError::*; 580 581 // read the header 582 let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| { 583 use err::ipv4::HeaderSliceError as I; 584 match err { 585 I::Len(err) => Len(err), 586 I::Content(err) => Header(err), 587 } 588 })?; 589 590 // check that the total length at least contains the header 591 let total_len: usize = header.total_len.into(); 592 let header_len = header.header_len(); 593 let payload_len = if total_len >= header_len { 594 total_len - header_len 595 } else { 596 return Err(Len(LenError { 597 required_len: header_len, 598 len: total_len, 599 len_source: LenSource::Ipv4HeaderTotalLen, 600 layer: Layer::Ipv4Packet, 601 layer_start_offset: 0, 602 })); 603 }; 604 605 // limit rest based on ipv4 total length 606 let header_rest = if payload_len > header_rest.len() { 607 return Err(Len(err::LenError { 608 required_len: total_len, 609 len: slice.len(), 610 len_source: LenSource::Slice, 611 layer: Layer::Ipv4Packet, 612 layer_start_offset: 0, 613 })); 614 } else { 615 unsafe { 616 // Safe as the payload_len <= header_rest.len is verified above 617 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len) 618 } 619 }; 620 621 // read the extension header 622 let (exts, next_header, exts_rest) = 623 Ipv4Extensions::from_slice(header.protocol, header_rest).map_err(|err| { 624 use err::ip_auth::HeaderSliceError as I; 625 match err { 626 I::Len(mut err) => { 627 err.layer_start_offset += header.header_len(); 628 err.len_source = LenSource::Ipv4HeaderTotalLen; 629 Len(err) 630 } 631 I::Content(err) => Exts(err), 632 } 633 })?; 634 635 let fragmented = header.is_fragmenting_payload(); 636 Ok(( 637 IpHeaders::Ipv4(header, exts), 638 IpPayloadSlice { 639 ip_number: next_header, 640 fragmented, 641 len_source: LenSource::Ipv4HeaderTotalLen, 642 payload: exts_rest, 643 }, 644 )) 645 } 646 647 /// Reads an IPv4 header & its extensions headers as far as is possible without encountering an 648 /// error & separates the payload from the given slice with less strict length checks. 649 /// This function is usefull for cut off packet or for packets with unset length fields). 650 /// 651 /// If you want to only receive correct IpPayloads use [`IpHeaders::from_ipv4_slice`] 652 /// instead. 653 /// 654 /// The main usecases for this functions are: 655 /// 656 /// * Parsing packets that have been cut off. This is, for example, useful to 657 /// parse packets returned via ICMP as these usually only contain the start. 658 /// * Parsing packets where the `total_len` (for IPv4) have not yet been set. 659 /// This can be useful when parsing packets which have been recorded in a 660 /// layer before the length field was set (e.g. before the operating 661 /// system set the length fields). 662 /// 663 /// # Differences to `from_ipv4_slice`: 664 /// 665 /// There are two main differences: 666 /// 667 /// * Errors in the expansion headers will only stop the parsing and return an `Ok` 668 /// with the successfully parsed parts and the error as optional. Only if an 669 /// unrecoverable error is encountered in the IP header itself an `Err` is returned. 670 /// In the normal `from_slice` function an `Err` is returned if an error is 671 /// encountered in an exteions header. 672 /// * `from_ipv4_slice_lax` ignores inconsistent `total_len` values. When the `total_len` 673 /// value in the IPv4 header are inconsistant the length of the given slice is 674 /// used as a substitute. 675 /// 676 /// You can check if the slice length was used as a substitude by checking 677 /// if the `len_source` value in the returned [`crate::LaxIpPayloadSlice`] is set to 678 /// [`LenSource::Slice`]. If a substitution was not needed `len_source` 679 /// is set to [`LenSource::Ipv4HeaderTotalLen`]. 680 /// 681 /// # When is the slice length used as a fallback? 682 /// 683 /// For IPv4 packets the slice length is used as a fallback/substitude 684 /// if the `total_length` field in the IPv4 header is: 685 /// 686 /// * Bigger then the given slice (payload cannot fully be seperated). 687 /// * Too small to contain at least the IPv4 header. from_ipv4_slice_lax( slice: &[u8], ) -> Result< ( IpHeaders, LaxIpPayloadSlice<'_>, Option<err::ip_auth::HeaderSliceError>, ), err::ip::LaxHeaderSliceError, >688 pub fn from_ipv4_slice_lax( 689 slice: &[u8], 690 ) -> Result< 691 ( 692 IpHeaders, 693 LaxIpPayloadSlice<'_>, 694 Option<err::ip_auth::HeaderSliceError>, 695 ), 696 err::ip::LaxHeaderSliceError, 697 > { 698 use err::ip::LaxHeaderSliceError::*; 699 700 // read the header 701 let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| { 702 use err::ip::HeaderError as O; 703 use err::ipv4::HeaderError as I1; 704 use err::ipv4::HeaderSliceError as I0; 705 match err { 706 I0::Len(err) => Len(err), 707 I0::Content(err) => Content(match err { 708 I1::UnexpectedVersion { version_number } => { 709 O::UnsupportedIpVersion { version_number } 710 } 711 I1::HeaderLengthSmallerThanHeader { ihl } => { 712 O::Ipv4HeaderLengthSmallerThanHeader { ihl } 713 } 714 }), 715 } 716 })?; 717 718 // check that the total len is at least containing the header len 719 let total_len: usize = header.total_len.into(); 720 721 // restrict the rest of the slice based on the total len (if the total_len is not conflicting) 722 let header_len = header.header_len(); 723 let (len_source, header_rest, incomplete) = if total_len < header_len { 724 // fallback to the rest of the slice 725 (LenSource::Slice, header_rest, false) 726 } else if header_rest.len() < total_len - header_len { 727 // fallback to the rest of the slice 728 (LenSource::Slice, header_rest, true) 729 } else { 730 ( 731 LenSource::Ipv4HeaderTotalLen, 732 unsafe { 733 core::slice::from_raw_parts( 734 header_rest.as_ptr(), 735 // SAFETY: Safe as slice length has been validated to be at least total_length_usize long 736 total_len - header_len, 737 ) 738 }, 739 false, 740 ) 741 }; 742 743 let (exts, next_protocol, payload, mut stop_err) = 744 Ipv4Extensions::from_slice_lax(header.protocol, header_rest); 745 746 use err::ip_auth::HeaderSliceError as I; 747 if let Some(I::Len(err)) = stop_err.as_mut() { 748 err.layer_start_offset += header.header_len(); 749 err.len_source = len_source; 750 } 751 752 let fragmented = header.is_fragmenting_payload(); 753 Ok(( 754 IpHeaders::Ipv4(header, exts), 755 LaxIpPayloadSlice { 756 incomplete, 757 ip_number: next_protocol, 758 fragmented, 759 len_source, 760 payload, 761 }, 762 stop_err, 763 )) 764 } 765 766 /// Read an IPv6 header & extension headers from a slice and return the slice 767 /// containing the payload (e.g. TCP, UDP etc.) length limited by payload_length 768 /// field in the IPv6 header. 769 /// 770 /// Note that slice length is used as a fallback value in case the 771 /// payload_length in the IPv6 is set to zero. This is a temporary workaround 772 /// to partially support jumbograms. from_ipv6_slice( slice: &[u8], ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv6::SliceError>773 pub fn from_ipv6_slice( 774 slice: &[u8], 775 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv6::SliceError> { 776 use err::ipv6::SliceError::*; 777 778 // read ipv6 header 779 let (header, header_rest) = Ipv6Header::from_slice(slice).map_err(|err| { 780 use err::ipv6::HeaderSliceError as I; 781 match err { 782 I::Len(err) => Len(err), 783 I::Content(err) => Header(err), 784 } 785 })?; 786 787 // restrict slice by the length specified in the header 788 let (header_payload, len_source) = 789 if 0 == header.payload_length && slice.len() > Ipv6Header::LEN { 790 // In case the payload_length is 0 assume that the entire 791 // rest of the slice is part of the packet until the jumbogram 792 // parameters can be parsed. 793 794 // TODO: Add payload length parsing from the jumbogram 795 (header_rest, LenSource::Slice) 796 } else { 797 let payload_len: usize = header.payload_length.into(); 798 if header_rest.len() < payload_len { 799 return Err(Len(LenError { 800 required_len: payload_len + Ipv6Header::LEN, 801 len: slice.len(), 802 len_source: LenSource::Slice, 803 layer: Layer::Ipv6Packet, 804 layer_start_offset: 0, 805 })); 806 } else { 807 unsafe { 808 ( 809 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len), 810 LenSource::Ipv6HeaderPayloadLen, 811 ) 812 } 813 } 814 }; 815 816 // read ipv6 extensions headers 817 let (exts, next_header, exts_rest) = 818 Ipv6Extensions::from_slice(header.next_header, header_payload).map_err(|err| { 819 use err::ipv6_exts::HeaderSliceError as I; 820 match err { 821 I::Len(mut err) => { 822 err.layer_start_offset += Ipv6Header::LEN; 823 err.len_source = len_source; 824 Len(err) 825 } 826 I::Content(err) => Exts(err), 827 } 828 })?; 829 830 let fragmented = exts.is_fragmenting_payload(); 831 Ok(( 832 IpHeaders::Ipv6(header, exts), 833 IpPayloadSlice { 834 ip_number: next_header, 835 fragmented, 836 len_source, 837 payload: exts_rest, 838 }, 839 )) 840 } 841 842 /// Reads an IPv6 header & its extensions headers as far as is possible without encountering an 843 /// error & separates the payload from the given slice with less strict length checks. 844 /// This function is usefull for cut off packet or for packets with unset length fields). 845 /// 846 /// If you want to only receive correct IpPayloads use [`IpHeaders::from_ipv6_slice`] 847 /// instead. 848 /// 849 /// The main usecases for this functions are: 850 /// 851 /// * Parsing packets that have been cut off. This is, for example, useful to 852 /// parse packets returned via ICMP as these usually only contain the start. 853 /// * Parsing packets where the `payload_length` (in the IPv6 header) has not 854 /// yet been set. This can be useful when parsing packets which have been 855 /// recorded in a layer before the length field was set (e.g. before the operating 856 /// system set the length fields). 857 /// 858 /// # Differences to `from_slice`: 859 /// 860 /// There are two main differences: 861 /// 862 /// * Errors in the expansion headers will only stop the parsing and return an `Ok` 863 /// with the successfully parsed parts and the error as optional. Only if an 864 /// unrecoverable error is encountered in the IP header itself an `Err` is returned. 865 /// In the normal `from_slice` function an `Err` is returned if an error is 866 /// encountered in an exteions header. 867 /// * `from_slice_lax` ignores inconsistent `payload_length` values. When the 868 /// `payload_length` value in the IPv6 header is inconsistant the length of 869 /// the given slice is used as a substitute. 870 /// 871 /// You can check if the slice length was used as a substitude by checking 872 /// if the `len_source` value in the returned [`LaxIpPayloadSlice`] is set to 873 /// [`LenSource::Slice`]. If a substitution was not needed `len_source` 874 /// is set to [`LenSource::Ipv6HeaderPayloadLen`]. 875 /// 876 /// # When is the slice length used as a fallback? 877 /// 878 /// The slice length is used as a fallback/substitude if the `payload_length` 879 /// field in the IPv6 header is 880 /// 881 /// * Bigger then the given slice (payload cannot fully be seperated). 882 /// * The value `0`. from_ipv6_slice_lax( slice: &[u8], ) -> Result< ( IpHeaders, LaxIpPayloadSlice<'_>, Option<(err::ipv6_exts::HeaderSliceError, Layer)>, ), err::ipv6::HeaderSliceError, >883 pub fn from_ipv6_slice_lax( 884 slice: &[u8], 885 ) -> Result< 886 ( 887 IpHeaders, 888 LaxIpPayloadSlice<'_>, 889 Option<(err::ipv6_exts::HeaderSliceError, Layer)>, 890 ), 891 err::ipv6::HeaderSliceError, 892 > { 893 // read ipv6 header 894 let (header, header_rest) = Ipv6Header::from_slice(slice)?; 895 896 // restrict slice by the length specified in the header 897 let payload_len: usize = header.payload_length.into(); 898 let (header_payload, len_source, incomplete) = 899 if payload_len == 0 && (false == header_rest.is_empty()) { 900 (header_rest, LenSource::Slice, false) 901 } else if payload_len > header_rest.len() { 902 (header_rest, LenSource::Slice, true) 903 } else { 904 unsafe { 905 ( 906 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len), 907 LenSource::Ipv6HeaderPayloadLen, 908 false, 909 ) 910 } 911 }; 912 913 // read ipv6 extensions headers 914 let (exts, next_header, exts_rest, mut stop_err) = 915 Ipv6Extensions::from_slice_lax(header.next_header, header_payload); 916 917 use err::ipv6_exts::HeaderSliceError as I; 918 if let Some((I::Len(err), _)) = stop_err.as_mut() { 919 err.layer_start_offset += Ipv6Header::LEN; 920 err.len_source = len_source; 921 }; 922 923 let fragmented = exts.is_fragmenting_payload(); 924 Ok(( 925 IpHeaders::Ipv6(header, exts), 926 LaxIpPayloadSlice { 927 incomplete, 928 ip_number: next_header, 929 fragmented, 930 len_source, 931 payload: exts_rest, 932 }, 933 stop_err, 934 )) 935 } 936 937 /// Reads an IP (v4 or v6) header from the current position (requires 938 /// crate feature `std`). 939 #[cfg(feature = "std")] 940 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] read<T: std::io::Read + std::io::Seek + Sized>( reader: &mut T, ) -> Result<(IpHeaders, IpNumber), err::ip::HeaderReadError>941 pub fn read<T: std::io::Read + std::io::Seek + Sized>( 942 reader: &mut T, 943 ) -> Result<(IpHeaders, IpNumber), err::ip::HeaderReadError> { 944 use crate::io::LimitedReader; 945 use err::ip::{HeaderError::*, HeaderReadError::*, HeadersError::*}; 946 947 let value = { 948 let mut buf = [0; 1]; 949 reader.read_exact(&mut buf).map_err(Io)?; 950 buf[0] 951 }; 952 match value >> 4 { 953 4 => { 954 // get internet header length 955 let ihl = value & 0xf; 956 957 // check that the ihl is correct 958 if ihl < 5 { 959 return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl }))); 960 } 961 962 // read the rest of the header 963 let header_len_u16 = u16::from(ihl) * 4; 964 let header_len = usize::from(header_len_u16); 965 let mut buffer = [0u8; Ipv4Header::MAX_LEN]; 966 buffer[0] = value; 967 reader.read_exact(&mut buffer[1..header_len]).map_err(Io)?; 968 969 let header = unsafe { 970 // SAFETY: Safe as both the IHL and slice len have been verified 971 Ipv4HeaderSlice::from_slice_unchecked(&buffer[..header_len]) 972 } 973 .to_header(); 974 975 // check that the total len is long enough to contain the header 976 let total_len = usize::from(header.total_len); 977 let mut reader = if total_len < header_len { 978 return Err(Len(LenError { 979 required_len: header_len, 980 len: total_len, 981 len_source: LenSource::Ipv4HeaderTotalLen, 982 layer: Layer::Ipv4Packet, 983 layer_start_offset: 0, 984 })); 985 } else { 986 // create a new reader that is limited by the total_len value length 987 LimitedReader::new( 988 reader, 989 total_len - header_len, 990 LenSource::Ipv4HeaderTotalLen, 991 header_len, 992 Layer::Ipv4Header, 993 ) 994 }; 995 996 // read the extension headers if present 997 Ipv4Extensions::read_limited(&mut reader, header.protocol) 998 .map(|(ext, next)| (IpHeaders::Ipv4(header, ext), next)) 999 .map_err(|err| { 1000 use err::ip_auth::HeaderLimitedReadError as I; 1001 match err { 1002 I::Io(err) => Io(err), 1003 I::Len(err) => Len(err), 1004 I::Content(err) => Content(Ipv4Ext(err)), 1005 } 1006 }) 1007 } 1008 6 => { 1009 let header = Ipv6Header::read_without_version(reader, value & 0xf).map_err(Io)?; 1010 1011 // create a new reader that is limited by the payload_len value length 1012 let mut reader = LimitedReader::new( 1013 reader, 1014 header.payload_length.into(), 1015 LenSource::Ipv6HeaderPayloadLen, 1016 header.header_len(), 1017 Layer::Ipv6Header, 1018 ); 1019 1020 Ipv6Extensions::read_limited(&mut reader, header.next_header) 1021 .map(|(ext, next)| (IpHeaders::Ipv6(header, ext), next)) 1022 .map_err(|err| { 1023 use err::ipv6_exts::HeaderLimitedReadError as I; 1024 match err { 1025 I::Io(err) => Io(err), 1026 I::Len(err) => Len(err), 1027 I::Content(err) => Content(Ipv6Ext(err)), 1028 } 1029 }) 1030 } 1031 version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))), 1032 } 1033 } 1034 1035 /// Writes an IP (v4 or v6) header to the current position (requires 1036 /// crate feature `std`). 1037 #[cfg(feature = "std")] 1038 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] write<T: std::io::Write + Sized>( &self, writer: &mut T, ) -> Result<(), HeadersWriteError>1039 pub fn write<T: std::io::Write + Sized>( 1040 &self, 1041 writer: &mut T, 1042 ) -> Result<(), HeadersWriteError> { 1043 use crate::IpHeaders::*; 1044 use HeadersWriteError::*; 1045 match *self { 1046 Ipv4(ref header, ref extensions) => { 1047 header.write(writer).map_err(Io)?; 1048 extensions.write(writer, header.protocol).map_err(|err| { 1049 use err::ipv4_exts::HeaderWriteError as I; 1050 match err { 1051 I::Io(err) => Io(err), 1052 I::Content(err) => Ipv4Exts(err), 1053 } 1054 }) 1055 } 1056 Ipv6(ref header, ref extensions) => { 1057 header.write(writer).map_err(Io)?; 1058 extensions.write(writer, header.next_header).map_err(|err| { 1059 use err::ipv6_exts::HeaderWriteError as I; 1060 match err { 1061 I::Io(err) => Io(err), 1062 I::Content(err) => Ipv6Exts(err), 1063 } 1064 }) 1065 } 1066 } 1067 } 1068 1069 /// Returns the size when the ip header & extensions are serialized header_len(&self) -> usize1070 pub fn header_len(&self) -> usize { 1071 use crate::IpHeaders::*; 1072 match *self { 1073 Ipv4(ref header, ref extensions) => header.header_len() + extensions.header_len(), 1074 Ipv6(_, ref extensions) => Ipv6Header::LEN + extensions.header_len(), 1075 } 1076 } 1077 1078 /// Returns the last next header number following the ip header 1079 /// and header extensions. next_header(&self) -> Result<IpNumber, err::ip_exts::ExtsWalkError>1080 pub fn next_header(&self) -> Result<IpNumber, err::ip_exts::ExtsWalkError> { 1081 use crate::err::ip_exts::ExtsWalkError::*; 1082 use crate::IpHeaders::*; 1083 match *self { 1084 Ipv4(ref header, ref extensions) => { 1085 extensions.next_header(header.protocol).map_err(Ipv4Exts) 1086 } 1087 Ipv6(ref header, ref extensions) => { 1088 extensions.next_header(header.next_header).map_err(Ipv6Exts) 1089 } 1090 } 1091 } 1092 1093 /// Sets all the next_header fields in the ipv4 & ipv6 header 1094 /// as well as in all extension headers and returns the ether 1095 /// type number. 1096 /// 1097 /// The given number will be set as the last "next_header" or 1098 /// protocol number. set_next_headers(&mut self, last_next_header: IpNumber) -> u161099 pub fn set_next_headers(&mut self, last_next_header: IpNumber) -> u16 { 1100 use IpHeaders::*; 1101 match self { 1102 Ipv4(ref mut header, ref mut extensions) => { 1103 header.protocol = extensions.set_next_headers(last_next_header); 1104 EtherType::IPV4.0 1105 } 1106 Ipv6(ref mut header, ref mut extensions) => { 1107 header.next_header = extensions.set_next_headers(last_next_header); 1108 EtherType::IPV4.0 1109 } 1110 } 1111 } 1112 1113 /// Tries to set the length field in the ip header given the length of data 1114 /// after the ip header and extension header(s). 1115 /// 1116 /// If the payload length is too large to be stored in the length fields 1117 /// of the ip header an error is returned. 1118 /// 1119 /// Note that this function will automatically add the length of the extension 1120 /// headers is they are present. set_payload_len(&mut self, len: usize) -> Result<(), ValueTooBigError<usize>>1121 pub fn set_payload_len(&mut self, len: usize) -> Result<(), ValueTooBigError<usize>> { 1122 use crate::err::ValueType; 1123 match self { 1124 IpHeaders::Ipv4(ipv4_hdr, exts) => { 1125 if let Some(complete_len) = len.checked_add(exts.header_len()) { 1126 ipv4_hdr.set_payload_len(complete_len) 1127 } else { 1128 Err(ValueTooBigError { 1129 actual: len, 1130 max_allowed: usize::from(u16::MAX) 1131 - ipv4_hdr.header_len() 1132 - exts.header_len(), 1133 value_type: ValueType::Ipv4PayloadLength, 1134 }) 1135 } 1136 } 1137 IpHeaders::Ipv6(ipv6_hdr, exts) => { 1138 if let Some(complete_len) = len.checked_add(exts.header_len()) { 1139 ipv6_hdr.set_payload_length(complete_len) 1140 } else { 1141 Err(ValueTooBigError { 1142 actual: len, 1143 max_allowed: usize::from(u16::MAX) - exts.header_len(), 1144 value_type: ValueType::Ipv4PayloadLength, 1145 }) 1146 } 1147 } 1148 } 1149 } 1150 1151 /// Returns true if the payload is fragmented based on the IPv4 header 1152 /// or the IPv6 fragment header. is_fragmenting_payload(&self) -> bool1153 pub fn is_fragmenting_payload(&self) -> bool { 1154 match self { 1155 IpHeaders::Ipv4(ipv4, _) => ipv4.is_fragmenting_payload(), 1156 IpHeaders::Ipv6(_, exts) => exts.is_fragmenting_payload(), 1157 } 1158 } 1159 } 1160 1161 #[cfg(test)] 1162 mod test { 1163 use crate::{ 1164 err::{ 1165 ip::{HeadersError, HeadersSliceError}, 1166 Layer, LenError, 1167 }, 1168 ip_number::*, 1169 test_gens::*, 1170 *, 1171 }; 1172 use alloc::{borrow::ToOwned, format, vec::Vec}; 1173 use proptest::prelude::*; 1174 use std::io::Cursor; 1175 1176 const EXTENSION_KNOWN_IP_NUMBERS: [IpNumber; 5] = [ 1177 AUTH, 1178 IPV6_DEST_OPTIONS, 1179 IPV6_HOP_BY_HOP, 1180 IPV6_FRAG, 1181 IPV6_ROUTE, 1182 ]; 1183 combine_v4(v4: &Ipv4Header, ext: &Ipv4Extensions, payload: &[u8]) -> IpHeaders1184 fn combine_v4(v4: &Ipv4Header, ext: &Ipv4Extensions, payload: &[u8]) -> IpHeaders { 1185 IpHeaders::Ipv4( 1186 { 1187 let mut v4 = v4.clone(); 1188 v4.protocol = if ext.auth.is_some() { AUTH } else { UDP }; 1189 v4.total_len = (v4.header_len() + ext.header_len() + payload.len()) as u16; 1190 v4.header_checksum = v4.calc_header_checksum(); 1191 v4 1192 }, 1193 ext.clone(), 1194 ) 1195 } 1196 combine_v6(v6: &Ipv6Header, ext: &Ipv6Extensions, payload: &[u8]) -> IpHeaders1197 fn combine_v6(v6: &Ipv6Header, ext: &Ipv6Extensions, payload: &[u8]) -> IpHeaders { 1198 let (ext, next_header) = { 1199 let mut ext = ext.clone(); 1200 let next_header = ext.set_next_headers(UDP); 1201 (ext, next_header) 1202 }; 1203 IpHeaders::Ipv6( 1204 { 1205 let mut v6 = v6.clone(); 1206 v6.next_header = next_header; 1207 v6.payload_length = (ext.header_len() + payload.len()) as u16; 1208 v6 1209 }, 1210 ext, 1211 ) 1212 } 1213 1214 proptest! { 1215 #[test] 1216 fn debug( 1217 v4 in ipv4_any(), 1218 v4_exts in ipv4_extensions_any(), 1219 v6 in ipv6_any(), 1220 v6_exts in ipv6_extensions_any(), 1221 ) { 1222 assert_eq!( 1223 format!( 1224 "Ipv4({:?}, {:?})", 1225 v4, 1226 v4_exts 1227 ), 1228 format!("{:?}", IpHeaders::Ipv4(v4, v4_exts)) 1229 ); 1230 assert_eq!( 1231 format!( 1232 "Ipv6({:?}, {:?})", 1233 v6, 1234 v6_exts 1235 ), 1236 format!("{:?}", IpHeaders::Ipv6(v6, v6_exts)) 1237 ); 1238 } 1239 } 1240 1241 proptest! { 1242 #[test] 1243 fn clone_eq( 1244 v4 in ipv4_any(), 1245 v4_exts in ipv4_extensions_any(), 1246 v6 in ipv6_any(), 1247 v6_exts in ipv6_extensions_any(), 1248 ) { 1249 { 1250 let v4 = IpHeaders::Ipv4(v4, v4_exts); 1251 assert_eq!(v4, v4.clone()); 1252 } 1253 { 1254 let v6 = IpHeaders::Ipv6(v6, v6_exts); 1255 assert_eq!(v6, v6.clone()); 1256 } 1257 } 1258 } 1259 1260 proptest! { 1261 #[test] 1262 fn ipv4( 1263 v4 in ipv4_any(), 1264 v4_exts in ipv4_extensions_any(), 1265 v6 in ipv6_any(), 1266 v6_exts in ipv6_extensions_any(), 1267 ) { 1268 assert_eq!( 1269 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv4(), 1270 Some((&v4, &v4_exts)) 1271 ); 1272 assert_eq!( 1273 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv4(), 1274 None 1275 ); 1276 } 1277 } 1278 1279 proptest! { 1280 #[test] 1281 fn ipv6( 1282 v4 in ipv4_any(), 1283 v4_exts in ipv4_extensions_any(), 1284 v6 in ipv6_any(), 1285 v6_exts in ipv6_extensions_any(), 1286 ) { 1287 assert_eq!( 1288 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv6(), 1289 None 1290 ); 1291 assert_eq!( 1292 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv6(), 1293 Some((&v6, &v6_exts)) 1294 ); 1295 } 1296 } 1297 1298 proptest! { 1299 #[test] 1300 #[allow(deprecated)] 1301 fn read_from_slice( 1302 v4 in ipv4_any(), 1303 v4_exts in ipv4_extensions_any(), 1304 ) { 1305 let header = combine_v4(&v4, &v4_exts, &[]); 1306 let mut buffer = Vec::with_capacity(header.header_len()); 1307 header.write(&mut buffer).unwrap(); 1308 1309 let actual = IpHeaders::read_from_slice(&buffer).unwrap(); 1310 assert_eq!(actual.0, header); 1311 assert_eq!(actual.1, header.next_header().unwrap()); 1312 assert_eq!(actual.2, &buffer[buffer.len()..]); 1313 } 1314 } 1315 1316 proptest! { 1317 #[test] 1318 fn ip_from_slice( 1319 v4 in ipv4_any(), 1320 v4_exts in ipv4_extensions_any(), 1321 v6 in ipv6_any(), 1322 v6_exts in ipv6_extensions_any(), 1323 ) { 1324 use err::ip::{HeadersError::*, HeaderError::*, HeadersSliceError::*}; 1325 1326 // empty error 1327 assert_eq!( 1328 IpHeaders::from_slice(&[]), 1329 Err(Len(err::LenError { 1330 required_len: 1, 1331 len: 0, 1332 len_source: LenSource::Slice, 1333 layer: err::Layer::IpHeader, 1334 layer_start_offset: 0, 1335 })) 1336 ); 1337 1338 // unknown version 1339 for version_number in 0..=0xfu8 { 1340 if version_number != 4 && version_number != 6 { 1341 assert_eq!( 1342 IpHeaders::from_slice(&[version_number << 4]), 1343 Err(Content(Ip(UnsupportedIpVersion { version_number }))) 1344 ); 1345 } 1346 } 1347 1348 let payload = [1,2,3,4]; 1349 1350 // v4 1351 { 1352 let header = combine_v4(&v4, &v4_exts, &payload); 1353 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1354 header.write(&mut buffer).unwrap(); 1355 buffer.extend_from_slice(&payload); 1356 buffer.push(1); // add some value to check the return slice 1357 1358 // read 1359 { 1360 let actual = IpHeaders::from_slice(&buffer).unwrap(); 1361 assert_eq!(&actual.0, &header); 1362 assert_eq!( 1363 actual.1, 1364 IpPayloadSlice{ 1365 ip_number: header.next_header().unwrap(), 1366 fragmented: header.is_fragmenting_payload(), 1367 len_source: LenSource::Ipv4HeaderTotalLen, 1368 payload: &payload 1369 } 1370 ); 1371 } 1372 1373 // read error ipv4 header 1374 IpHeaders::from_slice(&buffer[..1]).unwrap_err(); 1375 1376 // read error ipv4 extensions 1377 if v4_exts.header_len() > 0 { 1378 IpHeaders::from_slice(&buffer[..v4.header_len() + 1]).unwrap_err(); 1379 } 1380 1381 // total length smaller the header 1382 { 1383 let bad_total_len = (v4.header_len() - 1) as u16; 1384 1385 let mut buffer = buffer.clone(); 1386 // inject bad total_len 1387 let bad_total_len_be = bad_total_len.to_be_bytes(); 1388 buffer[2] = bad_total_len_be[0]; 1389 buffer[3] = bad_total_len_be[1]; 1390 assert_eq!( 1391 IpHeaders::from_slice(&buffer[..]).unwrap_err(), 1392 HeadersSliceError::Len(LenError{ 1393 required_len: v4.header_len(), 1394 len: bad_total_len as usize, 1395 len_source: LenSource::Ipv4HeaderTotalLen, 1396 layer: Layer::Ipv4Packet, 1397 layer_start_offset: 0, 1398 }) 1399 ); 1400 } 1401 } 1402 1403 // v6 1404 { 1405 let header = combine_v6(&v6, &v6_exts, &payload); 1406 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1407 header.write(&mut buffer).unwrap(); 1408 buffer.extend_from_slice(&payload); 1409 buffer.push(1); // add some value to check the return slice 1410 1411 // len error 1412 { 1413 let actual = IpHeaders::from_slice(&buffer).unwrap(); 1414 assert_eq!(&actual.0, &header); 1415 assert_eq!( 1416 actual.1, 1417 IpPayloadSlice{ 1418 ip_number: header.next_header().unwrap(), 1419 fragmented: header.is_fragmenting_payload(), 1420 len_source: LenSource::Ipv6HeaderPayloadLen, 1421 payload: &payload 1422 } 1423 ); 1424 } 1425 1426 // read error header 1427 IpHeaders::from_slice(&buffer[..1]).unwrap_err(); 1428 1429 // read error ipv4 extensions 1430 if v6_exts.header_len() > 0 { 1431 IpHeaders::from_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err(); 1432 } 1433 1434 // len error (with payload len zero) 1435 if v6_exts.header_len() > 0 { 1436 let mut buffer = buffer.clone(); 1437 1438 // inject zero as payload len 1439 buffer[4] = 0; 1440 buffer[5] = 0; 1441 1442 assert!( 1443 IpHeaders::from_slice( 1444 &buffer[..buffer.len() - payload.len() - 2] 1445 ).is_err() 1446 ); 1447 } 1448 } 1449 } 1450 } 1451 1452 proptest! { 1453 #[test] 1454 fn from_slice_lax( 1455 v4 in ipv4_any(), 1456 v4_exts in ipv4_extensions_any(), 1457 v6 in ipv6_any(), 1458 v6_exts in ipv6_extensions_any(), 1459 ) { 1460 use err::ip::{HeaderError::*, LaxHeaderSliceError::*}; 1461 1462 let payload = [1,2,3,4]; 1463 1464 // empty error 1465 assert_eq!( 1466 IpHeaders::from_slice_lax(&[]), 1467 Err(Len(err::LenError { 1468 required_len: 1, 1469 len: 0, 1470 len_source: LenSource::Slice, 1471 layer: err::Layer::IpHeader, 1472 layer_start_offset: 0, 1473 })) 1474 ); 1475 1476 // unknown version 1477 for version_number in 0..=0xfu8 { 1478 if version_number != 4 && version_number != 6 { 1479 assert_eq!( 1480 IpHeaders::from_slice_lax(&[version_number << 4]), 1481 Err(Content(UnsupportedIpVersion { version_number })) 1482 ); 1483 } 1484 } 1485 1486 // v4 1487 { 1488 let header = combine_v4(&v4, &v4_exts, &payload); 1489 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1490 header.write(&mut buffer).unwrap(); 1491 buffer.extend_from_slice(&payload); 1492 buffer.push(1); // add some value to check the return slice 1493 1494 // normal read 1495 { 1496 let actual = IpHeaders::from_slice_lax(&buffer).unwrap(); 1497 assert_eq!(&actual.0, &header); 1498 assert_eq!( 1499 actual.1, 1500 LaxIpPayloadSlice{ 1501 incomplete: false, 1502 ip_number: header.next_header().unwrap(), 1503 fragmented: header.is_fragmenting_payload(), 1504 len_source: LenSource::Ipv4HeaderTotalLen, 1505 payload: &payload 1506 } 1507 ); 1508 } 1509 1510 // error len smaller then min header len 1511 for len in 1..Ipv4Header::MIN_LEN { 1512 assert_eq!( 1513 IpHeaders::from_slice_lax(&buffer[..len]), 1514 Err(Len(err::LenError { 1515 required_len: Ipv4Header::MIN_LEN, 1516 len, 1517 len_source: LenSource::Slice, 1518 layer: err::Layer::Ipv4Header, 1519 layer_start_offset: 0, 1520 })) 1521 ); 1522 } 1523 1524 // ihl value error 1525 { 1526 let mut bad_ihl_buffer = buffer.clone(); 1527 for bad_ihl in 0..5 { 1528 bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl; 1529 assert_eq!( 1530 IpHeaders::from_slice_lax(&bad_ihl_buffer), 1531 Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl })) 1532 ); 1533 } 1534 } 1535 1536 // ihl len error 1537 for short_ihl in 5..usize::from(v4.ihl()) { 1538 assert_eq!( 1539 IpHeaders::from_slice_lax(&buffer[..4*short_ihl]), 1540 Err(Len(err::LenError { 1541 required_len: usize::from(v4.ihl())*4, 1542 len: 4*short_ihl, 1543 len_source: LenSource::Slice, 1544 layer: err::Layer::Ipv4Header, 1545 layer_start_offset: 0, 1546 })) 1547 ); 1548 } 1549 1550 // total_len bigger then slice len (fallback to slice len) 1551 for payload_len in 0..payload.len(){ 1552 let actual = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap(); 1553 assert_eq!(&actual.0, &header); 1554 assert_eq!( 1555 actual.1, 1556 LaxIpPayloadSlice{ 1557 incomplete: true, 1558 ip_number: header.next_header().unwrap(), 1559 fragmented: header.is_fragmenting_payload(), 1560 len_source: LenSource::Slice, 1561 payload: &payload[..payload_len] 1562 } 1563 ); 1564 } 1565 1566 // len error ipv4 extensions 1567 if v4_exts.header_len() > 0 { 1568 let (_, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + 1]).unwrap(); 1569 assert!(stop_err.is_some()); 1570 } 1571 1572 // content error ipv4 extensions 1573 if v4_exts.auth.is_some() { 1574 use err::ip_auth::HeaderError::ZeroPayloadLen; 1575 use err::ip_exts::HeadersSliceError::Content; 1576 use err::ip_exts::HeaderError::Ipv4Ext; 1577 1578 // introduce a auth header zero payload error 1579 let mut errored_buffer = buffer.clone(); 1580 // inject length zero into auth header (not valid, will 1581 // trigger a content error) 1582 errored_buffer[v4.header_len() + 1] = 0; 1583 1584 let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap(); 1585 1586 assert_eq!(stop_err, Some((Content(Ipv4Ext(ZeroPayloadLen)), Layer::IpAuthHeader))); 1587 } 1588 1589 // total length smaller the header (fallback to slice len) 1590 { 1591 let bad_total_len = (v4.header_len() - 1) as u16; 1592 1593 let mut buffer = buffer.clone(); 1594 // inject bad total_len 1595 let bad_total_len_be = bad_total_len.to_be_bytes(); 1596 buffer[2] = bad_total_len_be[0]; 1597 buffer[3] = bad_total_len_be[1]; 1598 1599 let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap(); 1600 1601 let (v4_header, v4_exts) = header.ipv4().unwrap(); 1602 let expected_headers = IpHeaders::Ipv4( 1603 { 1604 let mut expected_v4 = v4_header.clone(); 1605 expected_v4.total_len = bad_total_len; 1606 expected_v4 1607 }, 1608 v4_exts.clone() 1609 ); 1610 assert_eq!(&expected_headers, &actual.0); 1611 assert_eq!( 1612 actual.1, 1613 LaxIpPayloadSlice{ 1614 incomplete: false, 1615 ip_number: header.next_header().unwrap(), 1616 fragmented: header.is_fragmenting_payload(), 1617 len_source: LenSource::Slice, 1618 payload: &buffer[v4_header.header_len() + v4_exts.header_len()..], 1619 } 1620 ); 1621 } 1622 } 1623 1624 // v6 1625 { 1626 let header = combine_v6(&v6, &v6_exts, &payload); 1627 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1628 header.write(&mut buffer).unwrap(); 1629 buffer.extend_from_slice(&payload); 1630 buffer.push(1); // add some value to check the return slice 1631 1632 // normal read 1633 { 1634 let actual = IpHeaders::from_slice_lax(&buffer).unwrap(); 1635 assert_eq!(&actual.0, &header); 1636 assert_eq!( 1637 actual.1, 1638 LaxIpPayloadSlice{ 1639 incomplete: false, 1640 ip_number: header.next_header().unwrap(), 1641 fragmented: header.is_fragmenting_payload(), 1642 len_source: LenSource::Ipv6HeaderPayloadLen, 1643 payload: &payload 1644 } 1645 ); 1646 } 1647 1648 // smaller then header 1649 for len in 1..Ipv6Header::LEN { 1650 assert_eq!( 1651 IpHeaders::from_slice_lax(&buffer[..len]), 1652 Err(Len(err::LenError { 1653 required_len: Ipv6Header::LEN, 1654 len, 1655 len_source: LenSource::Slice, 1656 layer: err::Layer::Ipv6Header, 1657 layer_start_offset: 0, 1658 })) 1659 ); 1660 } 1661 1662 // extension len error 1663 if v6_exts.header_len() > 0 { 1664 let (actual, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v6.header_len() + 1]).unwrap(); 1665 assert_eq!(&actual.ipv6().as_ref().unwrap().0, &header.ipv6().as_ref().unwrap().0); 1666 assert!(stop_err.is_some()); 1667 } 1668 1669 // extension content error 1670 if v6_exts.auth.is_some() { 1671 use err::ip_auth::HeaderError::ZeroPayloadLen; 1672 use err::ip_exts::HeadersSliceError::Content; 1673 use err::ip_exts::HeaderError::Ipv6Ext; 1674 use err::ipv6_exts::HeaderError::IpAuth; 1675 1676 // introduce a auth header zero payload error 1677 let mut errored_buffer = buffer.clone(); 1678 let auth_offset = v6.header_len() + 1679 v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) + 1680 v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) + 1681 v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) + 1682 // routing.final_destination_options skiped, as after auth 1683 v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0); 1684 1685 // inject length zero into auth header (not valid, will 1686 // trigger a content error) 1687 errored_buffer[auth_offset + 1] = 0; 1688 1689 let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap(); 1690 assert_eq!( 1691 stop_err, 1692 Some((Content(Ipv6Ext(IpAuth(ZeroPayloadLen))), Layer::IpAuthHeader)) 1693 ); 1694 } 1695 1696 // slice smaller then payload len 1697 for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 { 1698 let actual = IpHeaders::from_slice_lax(&buffer[..len]).unwrap(); 1699 assert_eq!(&actual.0, &header); 1700 assert_eq!( 1701 actual.1, 1702 LaxIpPayloadSlice{ 1703 incomplete: true, 1704 ip_number: header.next_header().unwrap(), 1705 fragmented: header.is_fragmenting_payload(), 1706 len_source: LenSource::Slice, 1707 payload: &payload[..len - v6.header_len() - v6_exts.header_len()] 1708 } 1709 ); 1710 } 1711 1712 // payload len zero (fallback to slice len) 1713 { 1714 let mut buffer = buffer.clone(); 1715 // inject zero as payload len 1716 buffer[4] = 0; 1717 buffer[5] = 0; 1718 1719 let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap(); 1720 1721 let (v6_header, v6_exts) = header.ipv6().unwrap(); 1722 let expected_headers = IpHeaders::Ipv6( 1723 { 1724 let mut expected_v6 = v6_header.clone(); 1725 expected_v6.payload_length = 0; 1726 expected_v6 1727 }, 1728 v6_exts.clone() 1729 ); 1730 assert_eq!(&expected_headers, &actual.0); 1731 assert_eq!( 1732 actual.1, 1733 LaxIpPayloadSlice{ 1734 incomplete: false, 1735 ip_number: header.next_header().unwrap(), 1736 fragmented: header.is_fragmenting_payload(), 1737 len_source: LenSource::Slice, 1738 payload: &buffer[v6_header.header_len() + v6_exts.header_len()..], 1739 } 1740 ); 1741 } 1742 1743 } 1744 } 1745 } 1746 1747 proptest! { 1748 #[test] 1749 fn from_ipv4_slice( 1750 v4 in ipv4_any(), 1751 v4_exts in ipv4_extensions_any(), 1752 ) { 1753 let payload = [1,2,3,4]; 1754 1755 let header = combine_v4(&v4, &v4_exts, &payload); 1756 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1757 header.write(&mut buffer).unwrap(); 1758 buffer.extend_from_slice(&payload); 1759 buffer.push(1); // add some value to check the return slice 1760 1761 // read 1762 { 1763 let actual = IpHeaders::from_ipv4_slice(&buffer).unwrap(); 1764 assert_eq!(&actual.0, &header); 1765 assert_eq!( 1766 actual.1, 1767 IpPayloadSlice{ 1768 ip_number: header.next_header().unwrap(), 1769 fragmented: header.is_fragmenting_payload(), 1770 len_source: LenSource::Ipv4HeaderTotalLen, 1771 payload: &payload 1772 } 1773 ); 1774 } 1775 1776 // read error ipv4 header 1777 IpHeaders::from_ipv4_slice(&buffer[..1]).unwrap_err(); 1778 1779 // read error ipv4 extensions 1780 if v4_exts.header_len() > 0 { 1781 IpHeaders::from_ipv4_slice(&buffer[..v4.header_len() + 1]).unwrap_err(); 1782 } 1783 1784 // total length smaller the header 1785 { 1786 let bad_total_len = (v4.header_len() - 1) as u16; 1787 1788 let mut buffer = buffer.clone(); 1789 // inject bad total_len 1790 let bad_total_len_be = bad_total_len.to_be_bytes(); 1791 buffer[2] = bad_total_len_be[0]; 1792 buffer[3] = bad_total_len_be[1]; 1793 assert_eq!( 1794 IpHeaders::from_ipv4_slice(&buffer[..]).unwrap_err(), 1795 err::ipv4::SliceError::Len(LenError{ 1796 required_len: v4.header_len(), 1797 len: bad_total_len as usize, 1798 len_source: LenSource::Ipv4HeaderTotalLen, 1799 layer: Layer::Ipv4Packet, 1800 layer_start_offset: 0, 1801 }) 1802 ); 1803 } 1804 } 1805 } 1806 1807 proptest! { 1808 #[test] 1809 fn from_ipv4_slice_lax( 1810 v4 in ipv4_any(), 1811 v4_exts in ipv4_extensions_any() 1812 ) { 1813 use err::ip::{LaxHeaderSliceError::*, HeaderError::*}; 1814 1815 let payload = [1,2,3,4]; 1816 1817 // empty error 1818 assert_eq!( 1819 IpHeaders::from_ipv4_slice_lax(&[]), 1820 Err(Len(err::LenError { 1821 required_len: 20, 1822 len: 0, 1823 len_source: LenSource::Slice, 1824 layer: err::Layer::Ipv4Header, 1825 layer_start_offset: 0, 1826 })) 1827 ); 1828 1829 // build a buffer with a valid packet 1830 let header = combine_v4(&v4, &v4_exts, &payload); 1831 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1832 header.write(&mut buffer).unwrap(); 1833 buffer.extend_from_slice(&payload); 1834 buffer.push(1); // add some value to check the return slice 1835 1836 // normal read 1837 { 1838 let actual = IpHeaders::from_ipv4_slice_lax(&buffer).unwrap(); 1839 assert_eq!(&actual.0, &header); 1840 assert_eq!( 1841 actual.1, 1842 LaxIpPayloadSlice{ 1843 incomplete: false, 1844 ip_number: header.next_header().unwrap(), 1845 fragmented: header.is_fragmenting_payload(), 1846 len_source: LenSource::Ipv4HeaderTotalLen, 1847 payload: &payload 1848 } 1849 ); 1850 } 1851 1852 // error len smaller then min header len 1853 for len in 1..Ipv4Header::MIN_LEN { 1854 assert_eq!( 1855 IpHeaders::from_ipv4_slice_lax(&buffer[..len]), 1856 Err(Len(err::LenError { 1857 required_len: Ipv4Header::MIN_LEN, 1858 len, 1859 len_source: LenSource::Slice, 1860 layer: err::Layer::Ipv4Header, 1861 layer_start_offset: 0, 1862 })) 1863 ); 1864 } 1865 1866 // ihl value error 1867 { 1868 let mut bad_ihl_buffer = buffer.clone(); 1869 for bad_ihl in 0..5 { 1870 bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl; 1871 assert_eq!( 1872 IpHeaders::from_ipv4_slice_lax(&bad_ihl_buffer), 1873 Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl })) 1874 ); 1875 } 1876 } 1877 1878 // ihl len error 1879 for short_ihl in 5..usize::from(v4.ihl()) { 1880 assert_eq!( 1881 IpHeaders::from_ipv4_slice_lax(&buffer[..4*short_ihl]), 1882 Err(Len(err::LenError { 1883 required_len: usize::from(v4.ihl())*4, 1884 len: 4*short_ihl, 1885 len_source: LenSource::Slice, 1886 layer: err::Layer::Ipv4Header, 1887 layer_start_offset: 0, 1888 })) 1889 ); 1890 } 1891 1892 // total_len bigger then slice len (fallback to slice len) 1893 for payload_len in 0..payload.len(){ 1894 let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap(); 1895 assert_eq!(&actual.0, &header); 1896 assert_eq!( 1897 actual.1, 1898 LaxIpPayloadSlice{ 1899 incomplete: true, 1900 ip_number: header.next_header().unwrap(), 1901 fragmented: header.is_fragmenting_payload(), 1902 len_source: LenSource::Slice, 1903 payload: &payload[..payload_len] 1904 } 1905 ); 1906 } 1907 1908 // len error ipv4 extensions 1909 if v4_exts.header_len() > 0 { 1910 let (actual, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + 1]).unwrap(); 1911 assert_eq!(actual.ipv4().unwrap().0, header.ipv4().unwrap().0); 1912 assert!(stop_err.is_some()); 1913 } 1914 1915 // content error ipv4 extensions 1916 if v4_exts.auth.is_some() { 1917 use err::ip_auth::HeaderSliceError::Content; 1918 use err::ip_auth::HeaderError::ZeroPayloadLen; 1919 1920 // introduce a auth header zero payload error 1921 let mut errored_buffer = buffer.clone(); 1922 // inject length zero into auth header (not valid, will 1923 // trigger a content error) 1924 errored_buffer[v4.header_len() + 1] = 0; 1925 1926 let (_, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&errored_buffer).unwrap(); 1927 assert_eq!(stop_err, Some(Content(ZeroPayloadLen))); 1928 } 1929 1930 // total length smaller the header (fallback to slice len) 1931 { 1932 let bad_total_len = (v4.header_len() - 1) as u16; 1933 1934 let mut buffer = buffer.clone(); 1935 // inject bad total_len 1936 let bad_total_len_be = bad_total_len.to_be_bytes(); 1937 buffer[2] = bad_total_len_be[0]; 1938 buffer[3] = bad_total_len_be[1]; 1939 1940 let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..]).unwrap(); 1941 1942 let (v4_header, v4_exts) = header.ipv4().unwrap(); 1943 let expected_headers = IpHeaders::Ipv4( 1944 { 1945 let mut expected_v4 = v4_header.clone(); 1946 expected_v4.total_len = bad_total_len; 1947 expected_v4 1948 }, 1949 v4_exts.clone() 1950 ); 1951 assert_eq!(&expected_headers, &actual.0); 1952 assert_eq!( 1953 actual.1, 1954 LaxIpPayloadSlice{ 1955 incomplete: false, 1956 ip_number: header.next_header().unwrap(), 1957 fragmented: header.is_fragmenting_payload(), 1958 len_source: LenSource::Slice, 1959 payload: &buffer[v4_header.header_len() + v4_exts.header_len()..], 1960 } 1961 ); 1962 } 1963 } 1964 } 1965 1966 proptest! { 1967 #[test] 1968 fn from_ipv6_slice( 1969 v6 in ipv6_any(), 1970 v6_exts in ipv6_extensions_any(), 1971 ) { 1972 let payload = [1,2,3,4]; 1973 let header = combine_v6(&v6, &v6_exts, &payload); 1974 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 1975 header.write(&mut buffer).unwrap(); 1976 buffer.extend_from_slice(&payload); 1977 buffer.push(1); // add some value to check the return slice 1978 1979 // len error 1980 { 1981 let actual = IpHeaders::from_ipv6_slice(&buffer).unwrap(); 1982 assert_eq!(&actual.0, &header); 1983 assert_eq!( 1984 actual.1, 1985 IpPayloadSlice{ 1986 ip_number: header.next_header().unwrap(), 1987 fragmented: header.is_fragmenting_payload(), 1988 len_source: LenSource::Ipv6HeaderPayloadLen, 1989 payload: &payload 1990 } 1991 ); 1992 } 1993 1994 // read error header 1995 IpHeaders::from_ipv6_slice(&buffer[..1]).unwrap_err(); 1996 1997 // read error ipv4 extensions 1998 if v6_exts.header_len() > 0 { 1999 IpHeaders::from_ipv6_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err(); 2000 } 2001 2002 // len error (with payload len zero) 2003 if v6_exts.header_len() > 0 { 2004 let mut buffer = buffer.clone(); 2005 2006 // inject zero as payload len 2007 buffer[4] = 0; 2008 buffer[5] = 0; 2009 2010 assert!( 2011 IpHeaders::from_ipv6_slice( 2012 &buffer[..buffer.len() - payload.len() - 2] 2013 ).is_err() 2014 ); 2015 } 2016 } 2017 } 2018 2019 proptest! { 2020 #[test] 2021 fn from_ipv6_slice_lax( 2022 v6 in ipv6_any(), 2023 v6_exts in ipv6_extensions_any(), 2024 bad_version in 0..0xfu8 2025 ) { 2026 use err::ipv6::{HeaderError::*, HeaderSliceError::*}; 2027 2028 let payload = [1,2,3,4]; 2029 2030 // empty error 2031 assert_eq!( 2032 IpHeaders::from_ipv6_slice_lax(&[]), 2033 Err(Len(err::LenError { 2034 required_len: Ipv6Header::LEN, 2035 len: 0, 2036 len_source: LenSource::Slice, 2037 layer: err::Layer::Ipv6Header, 2038 layer_start_offset: 0, 2039 })) 2040 ); 2041 2042 // setup buffer with a valid packet 2043 let header = combine_v6(&v6, &v6_exts, &payload); 2044 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1); 2045 header.write(&mut buffer).unwrap(); 2046 buffer.extend_from_slice(&payload); 2047 buffer.push(1); // add some value to check the return slice 2048 2049 // unknown version 2050 if bad_version != 6 { 2051 let mut bad_vers_buffer = buffer.clone(); 2052 bad_vers_buffer[0] = (bad_vers_buffer[0] & 0xf) | (bad_version << 4); 2053 assert_eq!( 2054 IpHeaders::from_ipv6_slice_lax(&bad_vers_buffer), 2055 Err(Content(UnexpectedVersion { version_number: bad_version })) 2056 ); 2057 } 2058 2059 // normal read 2060 { 2061 let actual = IpHeaders::from_ipv6_slice_lax(&buffer).unwrap(); 2062 assert_eq!(&actual.0, &header); 2063 assert_eq!( 2064 actual.1, 2065 LaxIpPayloadSlice{ 2066 incomplete: false, 2067 ip_number: header.next_header().unwrap(), 2068 fragmented: header.is_fragmenting_payload(), 2069 len_source: LenSource::Ipv6HeaderPayloadLen, 2070 payload: &payload 2071 } 2072 ); 2073 } 2074 2075 // smaller then header 2076 for len in 1..Ipv6Header::LEN { 2077 assert_eq!( 2078 IpHeaders::from_ipv6_slice_lax(&buffer[..len]), 2079 Err(Len(err::LenError { 2080 required_len: Ipv6Header::LEN, 2081 len, 2082 len_source: LenSource::Slice, 2083 layer: err::Layer::Ipv6Header, 2084 layer_start_offset: 0, 2085 })) 2086 ); 2087 } 2088 2089 // extension len error 2090 if v6_exts.header_len() > 0 { 2091 let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&buffer[..v6.header_len() + 1]).unwrap(); 2092 assert!(err.is_some()); 2093 } 2094 2095 // extension content error 2096 if v6_exts.auth.is_some() { 2097 use err::ip_auth::HeaderError::ZeroPayloadLen; 2098 use err::ipv6_exts::{HeaderSliceError::Content, HeaderError::IpAuth}; 2099 2100 // introduce a auth header zero payload error 2101 let mut errored_buffer = buffer.clone(); 2102 let auth_offset = v6.header_len() + 2103 v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) + 2104 v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) + 2105 v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) + 2106 // routing.final_destination_options skiped, as after auth 2107 v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0); 2108 2109 // inject length zero into auth header (not valid, will 2110 // trigger a content error) 2111 errored_buffer[auth_offset + 1] = 0; 2112 let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&errored_buffer).unwrap(); 2113 assert_eq!(err, Some((Content(IpAuth(ZeroPayloadLen)), Layer::IpAuthHeader))); 2114 } 2115 2116 // slice smaller then payload len 2117 for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 { 2118 let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..len]).unwrap(); 2119 assert_eq!(&actual.0, &header); 2120 assert_eq!( 2121 actual.1, 2122 LaxIpPayloadSlice{ 2123 incomplete: true, 2124 ip_number: header.next_header().unwrap(), 2125 fragmented: header.is_fragmenting_payload(), 2126 len_source: LenSource::Slice, 2127 payload: &payload[..len - v6.header_len() - v6_exts.header_len()] 2128 } 2129 ); 2130 } 2131 2132 // payload len zero (fallback to slice len) 2133 { 2134 let mut buffer = buffer.clone(); 2135 // inject zero as payload len 2136 buffer[4] = 0; 2137 buffer[5] = 0; 2138 2139 let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..]).unwrap(); 2140 2141 let (v6_header, v6_exts) = header.ipv6().unwrap(); 2142 let expected_headers = IpHeaders::Ipv6( 2143 { 2144 let mut expected_v6 = v6_header.clone(); 2145 expected_v6.payload_length = 0; 2146 expected_v6 2147 }, 2148 v6_exts.clone() 2149 ); 2150 assert_eq!(&expected_headers, &actual.0); 2151 assert_eq!( 2152 actual.1, 2153 LaxIpPayloadSlice{ 2154 incomplete: false, 2155 ip_number: header.next_header().unwrap(), 2156 fragmented: header.is_fragmenting_payload(), 2157 len_source: LenSource::Slice, 2158 payload: &buffer[v6_header.header_len() + v6_exts.header_len()..], 2159 } 2160 ); 2161 } 2162 } 2163 } 2164 2165 proptest! { 2166 #[test] 2167 fn read( 2168 v4 in ipv4_any(), 2169 v4_exts in ipv4_extensions_any(), 2170 bad_ihl in 0u8..5u8, 2171 v6 in ipv6_any(), 2172 v6_exts in ipv6_extensions_any(), 2173 ) { 2174 use err::ip::{HeadersError::*, HeaderError::*}; 2175 2176 // no data error 2177 { 2178 let mut cursor = Cursor::new(&[]); 2179 assert!( 2180 IpHeaders::read(&mut cursor) 2181 .unwrap_err() 2182 .io() 2183 .is_some() 2184 ); 2185 } 2186 // version error 2187 { 2188 let mut cursor = Cursor::new(&[0xf << 4]); 2189 assert_eq!( 2190 IpHeaders::read(&mut cursor).unwrap_err().content().unwrap(), 2191 Ip(UnsupportedIpVersion { 2192 version_number: 0xf 2193 }) 2194 ); 2195 } 2196 // v4 2197 { 2198 let header = combine_v4(&v4, &v4_exts, &[]); 2199 let mut buffer = Vec::with_capacity(header.header_len()); 2200 header.write(&mut buffer).unwrap(); 2201 2202 // read 2203 { 2204 let mut cursor = Cursor::new(&buffer[..]); 2205 let actual = IpHeaders::read(&mut cursor).unwrap(); 2206 assert_eq!(actual.0, header); 2207 assert_eq!(actual.1, header.next_header().unwrap()); 2208 } 2209 2210 // read error ihl smaller then header 2211 { 2212 let mut buffer = buffer.clone(); 2213 // inject bad ihl 2214 buffer[0] = (buffer[0] & 0b1111_0000) | bad_ihl; 2215 let mut cursor = Cursor::new(&buffer[..]); 2216 assert_eq!( 2217 IpHeaders::read(&mut cursor) 2218 .unwrap_err() 2219 .content() 2220 .unwrap(), 2221 Ip(Ipv4HeaderLengthSmallerThanHeader{ 2222 ihl: bad_ihl 2223 }) 2224 ); 2225 } 2226 2227 // total length smaller the header 2228 { 2229 let bad_total_len = (v4.header_len() - 1) as u16; 2230 2231 let mut buffer = buffer.clone(); 2232 // inject bad total_len 2233 let bad_total_len_be = bad_total_len.to_be_bytes(); 2234 buffer[2] = bad_total_len_be[0]; 2235 buffer[3] = bad_total_len_be[1]; 2236 let mut cursor = Cursor::new(&buffer[..]); 2237 assert_eq!( 2238 IpHeaders::read(&mut cursor) 2239 .unwrap_err() 2240 .len() 2241 .unwrap(), 2242 LenError{ 2243 required_len: v4.header_len(), 2244 len: bad_total_len as usize, 2245 len_source: LenSource::Ipv4HeaderTotalLen, 2246 layer: Layer::Ipv4Packet, 2247 layer_start_offset: 0, 2248 } 2249 ); 2250 } 2251 2252 // read len error ipv4 2253 { 2254 let mut cursor = Cursor::new(&buffer[..1]); 2255 assert!( 2256 IpHeaders::read(&mut cursor) 2257 .unwrap_err() 2258 .io() 2259 .is_some() 2260 ); 2261 } 2262 2263 // read error ipv4 extensions 2264 if v4_exts.header_len() > 0 { 2265 let mut cursor = Cursor::new(&buffer[..v4.header_len() + 1]); 2266 IpHeaders::read(&mut cursor).unwrap_err(); 2267 } 2268 2269 // len error in extensions 2270 if v4_exts.auth.is_some() { 2271 let bad_total_len = (buffer.len() - 1) as u16; 2272 2273 let mut buffer = buffer.clone(); 2274 // inject bad total_len 2275 let bad_total_len_be = bad_total_len.to_be_bytes(); 2276 buffer[2] = bad_total_len_be[0]; 2277 buffer[3] = bad_total_len_be[1]; 2278 let mut cursor = Cursor::new(&buffer[..]); 2279 assert_eq!( 2280 IpHeaders::read(&mut cursor) 2281 .unwrap_err() 2282 .len() 2283 .unwrap(), 2284 LenError{ 2285 required_len: buffer.len() - v4.header_len(), 2286 len: bad_total_len as usize - v4.header_len(), 2287 len_source: LenSource::Ipv4HeaderTotalLen, 2288 layer: Layer::IpAuthHeader, 2289 layer_start_offset: v4.header_len(), 2290 } 2291 ); 2292 } 2293 2294 // extension content error 2295 if v4_exts.auth.is_some() { 2296 let mut buffer = buffer.clone(); 2297 // inject zero as header len 2298 buffer[v4.header_len() + 1] = 0; 2299 let mut cursor = Cursor::new(&buffer[..]); 2300 assert_eq!( 2301 IpHeaders::read(&mut cursor) 2302 .unwrap_err() 2303 .content() 2304 .unwrap(), 2305 HeadersError::Ipv4Ext( 2306 err::ip_auth::HeaderError::ZeroPayloadLen 2307 ) 2308 ); 2309 } 2310 } 2311 2312 // v6 2313 { 2314 let header = combine_v6(&v6, &v6_exts, &[]); 2315 let mut buffer = Vec::with_capacity(header.header_len()); 2316 header.write(&mut buffer).unwrap(); 2317 2318 // ok case 2319 { 2320 let mut cursor = Cursor::new(&buffer[..]); 2321 let actual = IpHeaders::read(&mut cursor).unwrap(); 2322 assert_eq!(actual.0, header); 2323 assert_eq!(actual.1, header.next_header().unwrap()); 2324 } 2325 2326 // io error in v6 header section 2327 { 2328 let mut cursor = Cursor::new(&buffer[..1]); 2329 assert!( 2330 IpHeaders::read(&mut cursor).unwrap_err().io().is_some() 2331 ); 2332 } 2333 2334 // io error ipv6 extensions 2335 if v6_exts.header_len() > 0 { 2336 let mut cursor = Cursor::new(&buffer[..Ipv6Header::LEN + 1]); 2337 assert!( 2338 IpHeaders::read(&mut cursor).unwrap_err().io().is_some() 2339 ); 2340 } 2341 2342 // len error in ipv6 extensions 2343 if v6_exts.header_len() > 0 { 2344 // inject an invalid length 2345 let mut buffer = buffer.clone(); 2346 let bad_payload_len = (buffer.len() - header.header_len()) as u16; 2347 let bad_payload_len_be = bad_payload_len.to_be_bytes(); 2348 buffer[4] = bad_payload_len_be[0]; 2349 buffer[5] = bad_payload_len_be[1]; 2350 // expect a length error 2351 let mut cursor = Cursor::new(&buffer[..]); 2352 assert!( 2353 IpHeaders::read(&mut cursor).unwrap_err().len().is_some() 2354 ); 2355 } 2356 2357 // extension content error 2358 if let Some(auth) = v6_exts.auth.as_ref() { 2359 // only do it if auth is the last header 2360 if v6_exts.routing.is_none() { 2361 // inject zero as header len 2362 let mut buffer = buffer.clone(); 2363 let auth_offset = buffer.len() - auth.header_len(); 2364 buffer[auth_offset + 1] = 0; 2365 let mut cursor = Cursor::new(&buffer[..]); 2366 assert_eq!( 2367 IpHeaders::read(&mut cursor) 2368 .unwrap_err() 2369 .content() 2370 .unwrap(), 2371 HeadersError::Ipv6Ext(err::ipv6_exts::HeaderError::IpAuth( 2372 err::ip_auth::HeaderError::ZeroPayloadLen 2373 )) 2374 ); 2375 } 2376 } 2377 } 2378 } 2379 } 2380 2381 proptest! { 2382 #[test] 2383 fn write( 2384 v4 in ipv4_any(), 2385 v4_exts in ipv4_extensions_any(), 2386 v6 in ipv6_any(), 2387 v6_exts in ipv6_extensions_any(), 2388 ) { 2389 // v4 2390 { 2391 let header = combine_v4(&v4, &v4_exts, &[]); 2392 let mut buffer = Vec::with_capacity(header.header_len()); 2393 header.write(&mut buffer).unwrap(); 2394 2395 let actual = IpHeaders::from_slice(&buffer).unwrap().0; 2396 assert_eq!(header, actual); 2397 2398 // write error v4 header 2399 { 2400 let mut buffer = [0u8;1]; 2401 let mut cursor = Cursor::new(&mut buffer[..]); 2402 assert!( 2403 header.write(&mut cursor) 2404 .unwrap_err() 2405 .io() 2406 .is_some() 2407 ); 2408 } 2409 2410 // write io error v4 extension headers 2411 if v4_exts.header_len() > 0 { 2412 let mut buffer = [0u8;Ipv4Header::MAX_LEN + 1]; 2413 let mut cursor = Cursor::new(&mut buffer[..v4.header_len() + 1]); 2414 assert!( 2415 header.write(&mut cursor) 2416 .unwrap_err() 2417 .io() 2418 .is_some() 2419 ); 2420 } 2421 2422 // write content error v4 extension headers 2423 if v4_exts.header_len() > 0 { 2424 // cause a missing reference error 2425 let header = IpHeaders::Ipv4( 2426 { 2427 let mut v4 = v4.clone(); 2428 // skips extension header 2429 v4.protocol = ip_number::UDP; 2430 v4.total_len = (v4.header_len() + v4_exts.header_len()) as u16; 2431 v4.header_checksum = v4.calc_header_checksum(); 2432 v4 2433 }, 2434 v4_exts.clone(), 2435 ); 2436 let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN]; 2437 let mut cursor = Cursor::new(&mut buffer[..]); 2438 assert!(header.write(&mut cursor).is_err()); 2439 } 2440 } 2441 2442 // v6 2443 { 2444 let header = combine_v6(&v6, &v6_exts, &[]); 2445 2446 // normal write 2447 let mut buffer = Vec::with_capacity(header.header_len()); 2448 header.write(&mut buffer).unwrap(); 2449 2450 let actual = IpHeaders::from_slice(&buffer).unwrap().0; 2451 assert_eq!(header, actual); 2452 2453 // write error v6 header 2454 { 2455 let mut buffer = [0u8;1]; 2456 let mut cursor = Cursor::new(&mut buffer[..]); 2457 assert!( 2458 header.write(&mut cursor) 2459 .unwrap_err() 2460 .io() 2461 .is_some() 2462 ); 2463 } 2464 2465 // write error v6 extension headers 2466 if v6_exts.header_len() > 0 { 2467 let mut buffer = [0u8;Ipv6Header::LEN + 1]; 2468 let mut cursor = Cursor::new(&mut buffer[..]); 2469 assert!( 2470 header.write(&mut cursor) 2471 .unwrap_err() 2472 .io() 2473 .is_some() 2474 ); 2475 } 2476 // write content error v4 extension headers 2477 if v6_exts.header_len() > 0 { 2478 // cause a missing reference error 2479 let header = IpHeaders::Ipv6( 2480 { 2481 let mut v6 = v6.clone(); 2482 // skips extension header 2483 v6.next_header = ip_number::UDP; 2484 v6.payload_length = v6_exts.header_len() as u16; 2485 v6 2486 }, 2487 v6_exts.clone(), 2488 ); 2489 let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN]; 2490 let mut cursor = Cursor::new(&mut buffer[..]); 2491 assert!(header.write(&mut cursor).is_err()); 2492 } 2493 } 2494 } 2495 } 2496 2497 proptest! { 2498 #[test] 2499 fn header_len( 2500 v4 in ipv4_any(), 2501 v4_exts in ipv4_extensions_any(), 2502 v6 in ipv6_any(), 2503 v6_exts in ipv6_extensions_any(), 2504 ) { 2505 assert_eq!( 2506 v4.header_len() + v4_exts.header_len(), 2507 IpHeaders::Ipv4(v4, v4_exts).header_len() 2508 ); 2509 assert_eq!( 2510 Ipv6Header::LEN + v6_exts.header_len(), 2511 IpHeaders::Ipv6(v6, v6_exts).header_len() 2512 ); 2513 } 2514 } 2515 2516 proptest! { 2517 #[test] 2518 fn next_header( 2519 v4 in ipv4_any(), 2520 v4_exts in ipv4_extensions_any(), 2521 v6 in ipv6_any(), 2522 v6_exts in ipv6_extensions_any(), 2523 post_header in ip_number_any() 2524 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(), 2525 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x) 2526 ) 2527 ) { 2528 { 2529 let mut header = v4.clone(); 2530 let mut exts = v4_exts.clone(); 2531 header.protocol = exts.set_next_headers(post_header); 2532 assert_eq!( 2533 Ok(post_header), 2534 IpHeaders::Ipv4(header, exts).next_header() 2535 ); 2536 } 2537 { 2538 let mut header = v6.clone(); 2539 let mut exts = v6_exts.clone(); 2540 header.next_header = exts.set_next_headers(post_header); 2541 assert_eq!( 2542 Ok(post_header), 2543 IpHeaders::Ipv6(header, exts).next_header() 2544 ); 2545 } 2546 } 2547 } 2548 2549 // TODO set_next_headers 2550 2551 proptest! { 2552 #[test] 2553 fn set_payload_len( 2554 v4 in ipv4_any(), 2555 v4_exts in ipv4_extensions_any(), 2556 v6 in ipv6_any(), 2557 v6_exts in ipv6_extensions_any(), 2558 payload_len in 0usize..10 2559 ) { 2560 // ipv4 (with valid payload length) 2561 { 2562 let mut actual = IpHeaders::Ipv4( 2563 v4.clone(), 2564 v4_exts.clone() 2565 ); 2566 actual.set_payload_len(payload_len).unwrap(); 2567 2568 assert_eq!( 2569 actual, 2570 IpHeaders::Ipv4( 2571 { 2572 let mut re = v4.clone(); 2573 re.set_payload_len(v4_exts.header_len() + payload_len).unwrap(); 2574 re 2575 }, 2576 v4_exts.clone() 2577 ) 2578 ); 2579 } 2580 // ipv6 (with valid payload length) 2581 { 2582 let mut actual = IpHeaders::Ipv6( 2583 v6.clone(), 2584 v6_exts.clone() 2585 ); 2586 actual.set_payload_len(payload_len).unwrap(); 2587 2588 assert_eq!( 2589 actual, 2590 IpHeaders::Ipv6( 2591 { 2592 let mut re = v6.clone(); 2593 re.set_payload_length(v6_exts.header_len() + payload_len).unwrap(); 2594 re 2595 }, 2596 v6_exts.clone() 2597 ) 2598 ); 2599 } 2600 2601 // v4 (with invalid size) 2602 { 2603 let mut actual = IpHeaders::Ipv4( 2604 v4.clone(), 2605 v4_exts.clone() 2606 ); 2607 assert!(actual.set_payload_len(usize::MAX).is_err()); 2608 } 2609 2610 // v6 (with invalid size) 2611 { 2612 let mut actual = IpHeaders::Ipv6( 2613 v6.clone(), 2614 v6_exts.clone() 2615 ); 2616 assert!(actual.set_payload_len(usize::MAX).is_err()); 2617 } 2618 } 2619 } 2620 2621 proptest! { 2622 #[test] 2623 fn is_fragmenting_payload( 2624 v4 in ipv4_any(), 2625 v4_exts in ipv4_extensions_any(), 2626 v6 in ipv6_any(), 2627 v6_exts in ipv6_extensions_any() 2628 ) { 2629 // ipv4 2630 assert_eq!( 2631 v4.is_fragmenting_payload(), 2632 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).is_fragmenting_payload() 2633 ); 2634 2635 // ipv6 2636 assert_eq!( 2637 v6_exts.is_fragmenting_payload(), 2638 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).is_fragmenting_payload() 2639 ); 2640 } 2641 } 2642 } 2643