1#[cfg(feature = "std")]
2use crate::err::ip::HeadersWriteError;
3use crate::err::{Layer, LenError, ValueTooBigError};
4use crate::*;
5
6pub type IpHeadersLaxFromSliceResult<'a> = (
16 IpHeaders,
17 LaxIpPayloadSlice<'a>,
18 Option<(err::ip_exts::HeadersSliceError, Layer)>,
19);
20
21pub type IpHeadersIpv6LaxFromSliceResult<'a> = (
31 IpHeaders,
32 LaxIpPayloadSlice<'a>,
33 Option<(err::ipv6_exts::HeaderSliceError, Layer)>,
34);
35
36#[derive(Clone, Debug, Eq, PartialEq)]
38#[allow(clippy::large_enum_variant)]
39pub enum IpHeaders {
40 Ipv4(Ipv4Header, Ipv4Extensions),
42 Ipv6(Ipv6Header, Ipv6Extensions),
44}
45
46impl IpHeaders {
47 pub const MAX_LEN: usize = Ipv6Header::LEN + Ipv6Extensions::MAX_LEN;
49
50 pub fn ipv4(&self) -> Option<(&Ipv4Header, &Ipv4Extensions)> {
52 if let IpHeaders::Ipv4(header, exts) = self {
53 Some((header, exts))
54 } else {
55 None
56 }
57 }
58
59 pub fn ipv6(&self) -> Option<(&Ipv6Header, &Ipv6Extensions)> {
61 if let IpHeaders::Ipv6(header, exts) = self {
62 Some((header, exts))
63 } else {
64 None
65 }
66 }
67
68 #[deprecated(since = "0.10.1", note = "Renamed to `IpHeaders::from_slice`")]
70 #[inline]
71 pub fn read_from_slice(
72 slice: &[u8],
73 ) -> Result<(IpHeaders, IpNumber, &[u8]), err::ip::HeadersSliceError> {
74 let (header, payload) = IpHeaders::from_slice(slice)?;
75 Ok((header, payload.ip_number, payload.payload))
76 }
77
78 pub fn from_slice(
88 slice: &[u8],
89 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ip::HeadersSliceError> {
90 use err::ip::{HeaderError::*, HeadersError::*, HeadersSliceError::*};
91
92 if slice.is_empty() {
93 Err(Len(err::LenError {
94 required_len: 1,
95 len: slice.len(),
96 len_source: LenSource::Slice,
97 layer: err::Layer::IpHeader,
98 layer_start_offset: 0,
99 }))
100 } else {
101 match slice[0] >> 4 {
102 4 => {
103 if slice.len() < Ipv4Header::MIN_LEN {
105 return Err(Len(err::LenError {
106 required_len: Ipv4Header::MIN_LEN,
107 len: slice.len(),
108 len_source: LenSource::Slice,
109 layer: err::Layer::Ipv4Header,
110 layer_start_offset: 0,
111 }));
112 }
113
114 let ihl = unsafe { slice.get_unchecked(0) } & 0xf;
120
121 if ihl < 5 {
123 return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl })));
124 }
125
126 let header_len = usize::from(ihl) * 4;
128 if slice.len() < header_len {
129 return Err(Len(LenError {
130 required_len: header_len,
131 len: slice.len(),
132 len_source: LenSource::Slice,
133 layer: Layer::Ipv4Header,
134 layer_start_offset: 0,
135 }));
136 }
137
138 let header = unsafe {
139 Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
141 slice.as_ptr(),
142 header_len,
143 ))
144 .to_header()
145 };
146
147 let total_len: usize = header.total_len.into();
149 if total_len < header_len {
150 return Err(Len(LenError {
151 required_len: header_len,
152 len: total_len,
153 len_source: LenSource::Ipv4HeaderTotalLen,
154 layer: Layer::Ipv4Packet,
155 layer_start_offset: 0,
156 }));
157 }
158
159 let rest = if slice.len() < total_len {
161 return Err(Len(LenError {
162 required_len: total_len,
163 len: slice.len(),
164 len_source: LenSource::Slice,
165 layer: Layer::Ipv4Packet,
166 layer_start_offset: 0,
167 }));
168 } else {
169 unsafe {
170 core::slice::from_raw_parts(
171 slice.as_ptr().add(header_len),
173 total_len - header_len,
175 )
176 }
177 };
178
179 let (exts, next_protocol, rest) =
180 Ipv4Extensions::from_slice(header.protocol, rest).map_err(|err| {
181 use err::ip_auth::HeaderSliceError as I;
182 match err {
183 I::Len(mut err) => {
184 err.layer_start_offset += header_len;
185 err.len_source = LenSource::Ipv4HeaderTotalLen;
186 Len(err)
187 }
188 I::Content(err) => Content(Ipv4Ext(err)),
189 }
190 })?;
191
192 let fragmented = header.is_fragmenting_payload();
193 Ok((
194 IpHeaders::Ipv4(header, exts),
195 IpPayloadSlice {
196 ip_number: next_protocol,
197 fragmented,
198 len_source: LenSource::Ipv4HeaderTotalLen,
199 payload: rest,
200 },
201 ))
202 }
203 6 => {
204 if slice.len() < Ipv6Header::LEN {
205 return Err(Len(err::LenError {
206 required_len: Ipv6Header::LEN,
207 len: slice.len(),
208 len_source: LenSource::Slice,
209 layer: err::Layer::Ipv6Header,
210 layer_start_offset: 0,
211 }));
212 }
213 let header = {
214 unsafe {
218 Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
219 slice.as_ptr(),
220 Ipv6Header::LEN,
221 ))
222 .to_header()
223 }
224 };
225
226 let (header_payload, len_source) =
228 if 0 == header.payload_length && slice.len() > Ipv6Header::LEN {
229 unsafe {
235 (
236 core::slice::from_raw_parts(
237 slice.as_ptr().add(Ipv6Header::LEN),
238 slice.len() - Ipv6Header::LEN,
239 ),
240 LenSource::Slice,
241 )
242 }
243 } else {
244 let payload_len: usize = header.payload_length.into();
245 let expected_len = Ipv6Header::LEN + payload_len;
246 if slice.len() < expected_len {
247 return Err(Len(LenError {
248 required_len: expected_len,
249 len: slice.len(),
250 len_source: LenSource::Slice,
251 layer: Layer::Ipv6Packet,
252 layer_start_offset: 0,
253 }));
254 } else {
255 unsafe {
256 (
257 core::slice::from_raw_parts(
258 slice.as_ptr().add(Ipv6Header::LEN),
259 payload_len,
260 ),
261 LenSource::Ipv6HeaderPayloadLen,
262 )
263 }
264 }
265 };
266
267 let (exts, next_header, rest) =
268 Ipv6Extensions::from_slice(header.next_header, header_payload).map_err(
269 |err| {
270 use err::ipv6_exts::HeaderSliceError as I;
271 match err {
272 I::Len(mut err) => {
273 err.layer_start_offset += Ipv6Header::LEN;
274 err.len_source = len_source;
275 Len(err)
276 }
277 I::Content(err) => Content(Ipv6Ext(err)),
278 }
279 },
280 )?;
281
282 let fragmented = exts.is_fragmenting_payload();
283 Ok((
284 IpHeaders::Ipv6(header, exts),
285 IpPayloadSlice {
286 ip_number: next_header,
287 fragmented,
288 len_source,
289 payload: rest,
290 },
291 ))
292 }
293 version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))),
294 }
295 }
296 }
297
298 pub fn from_slice_lax(
349 slice: &[u8],
350 ) -> Result<IpHeadersLaxFromSliceResult<'_>, err::ip::LaxHeaderSliceError> {
351 use err::ip::{HeaderError::*, LaxHeaderSliceError::*};
352
353 if slice.is_empty() {
354 Err(Len(err::LenError {
355 required_len: 1,
356 len: slice.len(),
357 len_source: LenSource::Slice,
358 layer: err::Layer::IpHeader,
359 layer_start_offset: 0,
360 }))
361 } else {
362 match slice[0] >> 4 {
363 4 => {
364 if slice.len() < Ipv4Header::MIN_LEN {
366 return Err(Len(err::LenError {
367 required_len: Ipv4Header::MIN_LEN,
368 len: slice.len(),
369 len_source: LenSource::Slice,
370 layer: err::Layer::Ipv4Header,
371 layer_start_offset: 0,
372 }));
373 }
374
375 let ihl = unsafe { slice.get_unchecked(0) } & 0xf;
381
382 if ihl < 5 {
384 return Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl }));
385 }
386
387 let header_len = usize::from(ihl) * 4;
389 if slice.len() < header_len {
390 return Err(Len(LenError {
391 required_len: header_len,
392 len: slice.len(),
393 len_source: LenSource::Slice,
394 layer: Layer::Ipv4Header,
395 layer_start_offset: 0,
396 }));
397 }
398
399 let header = unsafe {
400 Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
402 slice.as_ptr(),
403 header_len,
404 ))
405 .to_header()
406 };
407
408 let total_len: usize = header.total_len.into();
410
411 let (len_source, rest, incomplete) = if total_len < header_len {
413 (
415 LenSource::Slice,
416 unsafe {
417 core::slice::from_raw_parts(
418 slice.as_ptr().add(header_len),
420 slice.len() - header_len,
422 )
423 },
424 false,
425 )
426 } else if slice.len() < total_len {
427 (
428 LenSource::Slice,
429 unsafe {
430 core::slice::from_raw_parts(
431 slice.as_ptr().add(header_len),
433 slice.len() - header_len,
435 )
436 },
437 true,
438 )
439 } else {
440 (
441 LenSource::Ipv4HeaderTotalLen,
442 unsafe {
443 core::slice::from_raw_parts(
444 slice.as_ptr().add(header_len),
446 total_len - header_len,
448 )
449 },
450 false,
451 )
452 };
453
454 let (exts, next_protocol, rest, stop_err) =
455 Ipv4Extensions::from_slice_lax(header.protocol, rest);
456
457 let stop_err = stop_err.map(|err| {
458 use err::ip_auth::HeaderSliceError as I;
459 use err::ip_exts::HeaderError as OC;
460 use err::ip_exts::HeadersSliceError as O;
461 match err {
462 I::Len(mut l) => O::Len({
463 l.layer_start_offset += header_len;
464 l.len_source = len_source;
465 l
466 }),
467 I::Content(c) => O::Content(OC::Ipv4Ext(c)),
468 }
469 });
470
471 let fragmented = header.is_fragmenting_payload();
472 Ok((
473 IpHeaders::Ipv4(header, exts),
474 LaxIpPayloadSlice {
475 incomplete,
476 ip_number: next_protocol,
477 fragmented,
478 len_source,
479 payload: rest,
480 },
481 stop_err.map(|v| (v, Layer::IpAuthHeader)),
482 ))
483 }
484 6 => {
485 if slice.len() < Ipv6Header::LEN {
486 return Err(Len(err::LenError {
487 required_len: Ipv6Header::LEN,
488 len: slice.len(),
489 len_source: LenSource::Slice,
490 layer: err::Layer::Ipv6Header,
491 layer_start_offset: 0,
492 }));
493 }
494 let header = {
495 unsafe {
499 Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
500 slice.as_ptr(),
501 Ipv6Header::LEN,
502 ))
503 .to_header()
504 }
505 };
506
507 let payload_len = usize::from(header.payload_length);
509 let (header_payload, len_source, incomplete) =
510 if (header.payload_length == 0) && (Ipv6Header::LEN < slice.len()) {
511 unsafe {
513 (
514 core::slice::from_raw_parts(
515 slice.as_ptr().add(Ipv6Header::LEN),
517 slice.len() - Ipv6Header::LEN,
519 ),
520 LenSource::Slice,
521 false,
522 )
523 }
524 } else if (slice.len() - Ipv6Header::LEN) < payload_len {
525 unsafe {
526 (
527 core::slice::from_raw_parts(
528 slice.as_ptr().add(Ipv6Header::LEN),
530 slice.len() - Ipv6Header::LEN,
532 ),
533 LenSource::Slice,
534 true,
535 )
536 }
537 } else {
538 unsafe {
539 (
540 core::slice::from_raw_parts(
541 slice.as_ptr().add(Ipv6Header::LEN),
543 payload_len,
545 ),
546 LenSource::Ipv6HeaderPayloadLen,
547 false,
548 )
549 }
550 };
551
552 let (exts, next_header, rest, stop_err) =
553 Ipv6Extensions::from_slice_lax(header.next_header, header_payload);
554
555 let stop_err = stop_err.map(|(err, layer)| {
556 use err::ip_exts::HeaderError::Ipv6Ext;
557 use err::ip_exts::HeadersSliceError as O;
558 use err::ipv6_exts::HeaderSliceError as I;
559 (
560 match err {
561 I::Len(mut l) => {
562 l.layer_start_offset += Ipv6Header::LEN;
563 l.len_source = len_source;
564 O::Len(l)
565 }
566 I::Content(c) => O::Content(Ipv6Ext(c)),
567 },
568 layer,
569 )
570 });
571
572 let fragmented = exts.is_fragmenting_payload();
573 Ok((
574 IpHeaders::Ipv6(header, exts),
575 LaxIpPayloadSlice {
576 incomplete,
577 ip_number: next_header,
578 fragmented,
579 len_source,
580 payload: rest,
581 },
582 stop_err,
583 ))
584 }
585 version_number => Err(Content(UnsupportedIpVersion { version_number })),
586 }
587 }
588 }
589
590 pub fn from_ipv4_slice(
600 slice: &[u8],
601 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv4::SliceError> {
602 use err::ipv4::SliceError::*;
603
604 let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| {
606 use err::ipv4::HeaderSliceError as I;
607 match err {
608 I::Len(err) => Len(err),
609 I::Content(err) => Header(err),
610 }
611 })?;
612
613 let total_len: usize = header.total_len.into();
615 let header_len = header.header_len();
616 let payload_len = if total_len >= header_len {
617 total_len - header_len
618 } else {
619 return Err(Len(LenError {
620 required_len: header_len,
621 len: total_len,
622 len_source: LenSource::Ipv4HeaderTotalLen,
623 layer: Layer::Ipv4Packet,
624 layer_start_offset: 0,
625 }));
626 };
627
628 let header_rest = if payload_len > header_rest.len() {
630 return Err(Len(err::LenError {
631 required_len: total_len,
632 len: slice.len(),
633 len_source: LenSource::Slice,
634 layer: Layer::Ipv4Packet,
635 layer_start_offset: 0,
636 }));
637 } else {
638 unsafe {
639 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len)
641 }
642 };
643
644 let (exts, next_header, exts_rest) =
646 Ipv4Extensions::from_slice(header.protocol, header_rest).map_err(|err| {
647 use err::ip_auth::HeaderSliceError as I;
648 match err {
649 I::Len(mut err) => {
650 err.layer_start_offset += header.header_len();
651 err.len_source = LenSource::Ipv4HeaderTotalLen;
652 Len(err)
653 }
654 I::Content(err) => Exts(err),
655 }
656 })?;
657
658 let fragmented = header.is_fragmenting_payload();
659 Ok((
660 IpHeaders::Ipv4(header, exts),
661 IpPayloadSlice {
662 ip_number: next_header,
663 fragmented,
664 len_source: LenSource::Ipv4HeaderTotalLen,
665 payload: exts_rest,
666 },
667 ))
668 }
669
670 pub fn from_ipv4_slice_lax(
712 slice: &[u8],
713 ) -> Result<
714 (
715 IpHeaders,
716 LaxIpPayloadSlice<'_>,
717 Option<err::ip_auth::HeaderSliceError>,
718 ),
719 err::ip::LaxHeaderSliceError,
720 > {
721 use err::ip::LaxHeaderSliceError::*;
722
723 let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| {
725 use err::ip::HeaderError as O;
726 use err::ipv4::HeaderError as I1;
727 use err::ipv4::HeaderSliceError as I0;
728 match err {
729 I0::Len(err) => Len(err),
730 I0::Content(err) => Content(match err {
731 I1::UnexpectedVersion { version_number } => {
732 O::UnsupportedIpVersion { version_number }
733 }
734 I1::HeaderLengthSmallerThanHeader { ihl } => {
735 O::Ipv4HeaderLengthSmallerThanHeader { ihl }
736 }
737 }),
738 }
739 })?;
740
741 let total_len: usize = header.total_len.into();
743
744 let header_len = header.header_len();
746 let (len_source, header_rest, incomplete) = if total_len < header_len {
747 (LenSource::Slice, header_rest, false)
749 } else if header_rest.len() < total_len - header_len {
750 (LenSource::Slice, header_rest, true)
752 } else {
753 (
754 LenSource::Ipv4HeaderTotalLen,
755 unsafe {
756 core::slice::from_raw_parts(
757 header_rest.as_ptr(),
758 total_len - header_len,
760 )
761 },
762 false,
763 )
764 };
765
766 let (exts, next_protocol, payload, mut stop_err) =
767 Ipv4Extensions::from_slice_lax(header.protocol, header_rest);
768
769 use err::ip_auth::HeaderSliceError as I;
770 if let Some(I::Len(err)) = stop_err.as_mut() {
771 err.layer_start_offset += header.header_len();
772 err.len_source = len_source;
773 }
774
775 let fragmented = header.is_fragmenting_payload();
776 Ok((
777 IpHeaders::Ipv4(header, exts),
778 LaxIpPayloadSlice {
779 incomplete,
780 ip_number: next_protocol,
781 fragmented,
782 len_source,
783 payload,
784 },
785 stop_err,
786 ))
787 }
788
789 pub fn from_ipv6_slice(
797 slice: &[u8],
798 ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv6::SliceError> {
799 use err::ipv6::SliceError::*;
800
801 let (header, header_rest) = Ipv6Header::from_slice(slice).map_err(|err| {
803 use err::ipv6::HeaderSliceError as I;
804 match err {
805 I::Len(err) => Len(err),
806 I::Content(err) => Header(err),
807 }
808 })?;
809
810 let (header_payload, len_source) =
812 if 0 == header.payload_length && slice.len() > Ipv6Header::LEN {
813 (header_rest, LenSource::Slice)
819 } else {
820 let payload_len: usize = header.payload_length.into();
821 if header_rest.len() < payload_len {
822 return Err(Len(LenError {
823 required_len: payload_len + Ipv6Header::LEN,
824 len: slice.len(),
825 len_source: LenSource::Slice,
826 layer: Layer::Ipv6Packet,
827 layer_start_offset: 0,
828 }));
829 } else {
830 unsafe {
831 (
832 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len),
833 LenSource::Ipv6HeaderPayloadLen,
834 )
835 }
836 }
837 };
838
839 let (exts, next_header, exts_rest) =
841 Ipv6Extensions::from_slice(header.next_header, header_payload).map_err(|err| {
842 use err::ipv6_exts::HeaderSliceError as I;
843 match err {
844 I::Len(mut err) => {
845 err.layer_start_offset += Ipv6Header::LEN;
846 err.len_source = len_source;
847 Len(err)
848 }
849 I::Content(err) => Exts(err),
850 }
851 })?;
852
853 let fragmented = exts.is_fragmenting_payload();
854 Ok((
855 IpHeaders::Ipv6(header, exts),
856 IpPayloadSlice {
857 ip_number: next_header,
858 fragmented,
859 len_source,
860 payload: exts_rest,
861 },
862 ))
863 }
864
865 pub fn from_ipv6_slice_lax(
907 slice: &[u8],
908 ) -> Result<IpHeadersIpv6LaxFromSliceResult<'_>, err::ipv6::HeaderSliceError> {
909 let (header, header_rest) = Ipv6Header::from_slice(slice)?;
911
912 let payload_len: usize = header.payload_length.into();
914 let (header_payload, len_source, incomplete) =
915 if payload_len == 0 && (false == header_rest.is_empty()) {
916 (header_rest, LenSource::Slice, false)
917 } else if payload_len > header_rest.len() {
918 (header_rest, LenSource::Slice, true)
919 } else {
920 unsafe {
921 (
922 core::slice::from_raw_parts(header_rest.as_ptr(), payload_len),
923 LenSource::Ipv6HeaderPayloadLen,
924 false,
925 )
926 }
927 };
928
929 let (exts, next_header, exts_rest, mut stop_err) =
931 Ipv6Extensions::from_slice_lax(header.next_header, header_payload);
932
933 use err::ipv6_exts::HeaderSliceError as I;
934 if let Some((I::Len(err), _)) = stop_err.as_mut() {
935 err.layer_start_offset += Ipv6Header::LEN;
936 err.len_source = len_source;
937 };
938
939 let fragmented = exts.is_fragmenting_payload();
940 Ok((
941 IpHeaders::Ipv6(header, exts),
942 LaxIpPayloadSlice {
943 incomplete,
944 ip_number: next_header,
945 fragmented,
946 len_source,
947 payload: exts_rest,
948 },
949 stop_err,
950 ))
951 }
952
953 #[cfg(feature = "std")]
956 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
957 pub fn read<T: std::io::Read + std::io::Seek + Sized>(
958 reader: &mut T,
959 ) -> Result<(IpHeaders, IpNumber), err::ip::HeaderReadError> {
960 use crate::io::LimitedReader;
961 use err::ip::{HeaderError::*, HeaderReadError::*, HeadersError::*};
962
963 let value = {
964 let mut buf = [0; 1];
965 reader.read_exact(&mut buf).map_err(Io)?;
966 buf[0]
967 };
968 match value >> 4 {
969 4 => {
970 let ihl = value & 0xf;
972
973 if ihl < 5 {
975 return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl })));
976 }
977
978 let header_len_u16 = u16::from(ihl) * 4;
980 let header_len = usize::from(header_len_u16);
981 let mut buffer = [0u8; Ipv4Header::MAX_LEN];
982 buffer[0] = value;
983 reader.read_exact(&mut buffer[1..header_len]).map_err(Io)?;
984
985 let header = unsafe {
986 Ipv4HeaderSlice::from_slice_unchecked(&buffer[..header_len])
988 }
989 .to_header();
990
991 let total_len = usize::from(header.total_len);
993 let mut reader = if total_len < header_len {
994 return Err(Len(LenError {
995 required_len: header_len,
996 len: total_len,
997 len_source: LenSource::Ipv4HeaderTotalLen,
998 layer: Layer::Ipv4Packet,
999 layer_start_offset: 0,
1000 }));
1001 } else {
1002 LimitedReader::new(
1004 reader,
1005 total_len - header_len,
1006 LenSource::Ipv4HeaderTotalLen,
1007 header_len,
1008 Layer::Ipv4Header,
1009 )
1010 };
1011
1012 Ipv4Extensions::read_limited(&mut reader, header.protocol)
1014 .map(|(ext, next)| (IpHeaders::Ipv4(header, ext), next))
1015 .map_err(|err| {
1016 use err::ip_auth::HeaderLimitedReadError as I;
1017 match err {
1018 I::Io(err) => Io(err),
1019 I::Len(err) => Len(err),
1020 I::Content(err) => Content(Ipv4Ext(err)),
1021 }
1022 })
1023 }
1024 6 => {
1025 let header = Ipv6Header::read_without_version(reader, value & 0xf).map_err(Io)?;
1026
1027 let mut reader = LimitedReader::new(
1029 reader,
1030 header.payload_length.into(),
1031 LenSource::Ipv6HeaderPayloadLen,
1032 header.header_len(),
1033 Layer::Ipv6Header,
1034 );
1035
1036 Ipv6Extensions::read_limited(&mut reader, header.next_header)
1037 .map(|(ext, next)| (IpHeaders::Ipv6(header, ext), next))
1038 .map_err(|err| {
1039 use err::ipv6_exts::HeaderLimitedReadError as I;
1040 match err {
1041 I::Io(err) => Io(err),
1042 I::Len(err) => Len(err),
1043 I::Content(err) => Content(Ipv6Ext(err)),
1044 }
1045 })
1046 }
1047 version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))),
1048 }
1049 }
1050
1051 #[cfg(feature = "std")]
1054 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1055 pub fn write<T: std::io::Write + Sized>(
1056 &self,
1057 writer: &mut T,
1058 ) -> Result<(), HeadersWriteError> {
1059 use crate::IpHeaders::*;
1060 use HeadersWriteError::*;
1061 match *self {
1062 Ipv4(ref header, ref extensions) => {
1063 header.write(writer).map_err(Io)?;
1064 extensions.write(writer, header.protocol).map_err(|err| {
1065 use err::ipv4_exts::HeaderWriteError as I;
1066 match err {
1067 I::Io(err) => Io(err),
1068 I::Content(err) => Ipv4Exts(err),
1069 }
1070 })
1071 }
1072 Ipv6(ref header, ref extensions) => {
1073 header.write(writer).map_err(Io)?;
1074 extensions.write(writer, header.next_header).map_err(|err| {
1075 use err::ipv6_exts::HeaderWriteError as I;
1076 match err {
1077 I::Io(err) => Io(err),
1078 I::Content(err) => Ipv6Exts(err),
1079 }
1080 })
1081 }
1082 }
1083 }
1084
1085 pub fn header_len(&self) -> usize {
1087 use crate::IpHeaders::*;
1088 match *self {
1089 Ipv4(ref header, ref extensions) => header.header_len() + extensions.header_len(),
1090 Ipv6(_, ref extensions) => Ipv6Header::LEN + extensions.header_len(),
1091 }
1092 }
1093
1094 pub fn next_header(&self) -> Result<IpNumber, err::ip_exts::ExtsWalkError> {
1097 use crate::err::ip_exts::ExtsWalkError::*;
1098 use crate::IpHeaders::*;
1099 match *self {
1100 Ipv4(ref header, ref extensions) => {
1101 extensions.next_header(header.protocol).map_err(Ipv4Exts)
1102 }
1103 Ipv6(ref header, ref extensions) => {
1104 extensions.next_header(header.next_header).map_err(Ipv6Exts)
1105 }
1106 }
1107 }
1108
1109 pub fn set_next_headers(&mut self, last_next_header: IpNumber) -> EtherType {
1116 use IpHeaders::*;
1117 match self {
1118 Ipv4(ref mut header, ref mut extensions) => {
1119 header.protocol = extensions.set_next_headers(last_next_header);
1120 EtherType::IPV4
1121 }
1122 Ipv6(ref mut header, ref mut extensions) => {
1123 header.next_header = extensions.set_next_headers(last_next_header);
1124 EtherType::IPV4
1125 }
1126 }
1127 }
1128
1129 pub fn set_payload_len(&mut self, len: usize) -> Result<(), ValueTooBigError<usize>> {
1138 use crate::err::ValueType;
1139 match self {
1140 IpHeaders::Ipv4(ipv4_hdr, exts) => {
1141 if let Some(complete_len) = len.checked_add(exts.header_len()) {
1142 ipv4_hdr.set_payload_len(complete_len)
1143 } else {
1144 Err(ValueTooBigError {
1145 actual: len,
1146 max_allowed: usize::from(u16::MAX)
1147 - ipv4_hdr.header_len()
1148 - exts.header_len(),
1149 value_type: ValueType::Ipv4PayloadLength,
1150 })
1151 }
1152 }
1153 IpHeaders::Ipv6(ipv6_hdr, exts) => {
1154 if let Some(complete_len) = len.checked_add(exts.header_len()) {
1155 ipv6_hdr.set_payload_length(complete_len)
1156 } else {
1157 Err(ValueTooBigError {
1158 actual: len,
1159 max_allowed: usize::from(u16::MAX) - exts.header_len(),
1160 value_type: ValueType::Ipv4PayloadLength,
1161 })
1162 }
1163 }
1164 }
1165 }
1166
1167 pub fn is_fragmenting_payload(&self) -> bool {
1170 match self {
1171 IpHeaders::Ipv4(ipv4, _) => ipv4.is_fragmenting_payload(),
1172 IpHeaders::Ipv6(_, exts) => exts.is_fragmenting_payload(),
1173 }
1174 }
1175}
1176
1177#[cfg(test)]
1178mod test {
1179 use crate::{
1180 err::{
1181 ip::{HeadersError, HeadersSliceError},
1182 Layer, LenError,
1183 },
1184 ip_number::*,
1185 test_gens::*,
1186 *,
1187 };
1188 use alloc::{borrow::ToOwned, format, vec::Vec};
1189 use proptest::prelude::*;
1190 use std::io::Cursor;
1191
1192 const EXTENSION_KNOWN_IP_NUMBERS: [IpNumber; 5] = [
1193 AUTH,
1194 IPV6_DEST_OPTIONS,
1195 IPV6_HOP_BY_HOP,
1196 IPV6_FRAG,
1197 IPV6_ROUTE,
1198 ];
1199
1200 fn combine_v4(v4: &Ipv4Header, ext: &Ipv4Extensions, payload: &[u8]) -> IpHeaders {
1201 IpHeaders::Ipv4(
1202 {
1203 let mut v4 = v4.clone();
1204 v4.protocol = if ext.auth.is_some() { AUTH } else { UDP };
1205 v4.total_len = (v4.header_len() + ext.header_len() + payload.len()) as u16;
1206 v4.header_checksum = v4.calc_header_checksum();
1207 v4
1208 },
1209 ext.clone(),
1210 )
1211 }
1212
1213 fn combine_v6(v6: &Ipv6Header, ext: &Ipv6Extensions, payload: &[u8]) -> IpHeaders {
1214 let (ext, next_header) = {
1215 let mut ext = ext.clone();
1216 let next_header = ext.set_next_headers(UDP);
1217 (ext, next_header)
1218 };
1219 IpHeaders::Ipv6(
1220 {
1221 let mut v6 = v6.clone();
1222 v6.next_header = next_header;
1223 v6.payload_length = (ext.header_len() + payload.len()) as u16;
1224 v6
1225 },
1226 ext,
1227 )
1228 }
1229
1230 proptest! {
1231 #[test]
1232 fn debug(
1233 v4 in ipv4_any(),
1234 v4_exts in ipv4_extensions_any(),
1235 v6 in ipv6_any(),
1236 v6_exts in ipv6_extensions_any(),
1237 ) {
1238 assert_eq!(
1239 format!(
1240 "Ipv4({:?}, {:?})",
1241 v4,
1242 v4_exts
1243 ),
1244 format!("{:?}", IpHeaders::Ipv4(v4, v4_exts))
1245 );
1246 assert_eq!(
1247 format!(
1248 "Ipv6({:?}, {:?})",
1249 v6,
1250 v6_exts
1251 ),
1252 format!("{:?}", IpHeaders::Ipv6(v6, v6_exts))
1253 );
1254 }
1255 }
1256
1257 proptest! {
1258 #[test]
1259 fn clone_eq(
1260 v4 in ipv4_any(),
1261 v4_exts in ipv4_extensions_any(),
1262 v6 in ipv6_any(),
1263 v6_exts in ipv6_extensions_any(),
1264 ) {
1265 {
1266 let v4 = IpHeaders::Ipv4(v4, v4_exts);
1267 assert_eq!(v4, v4.clone());
1268 }
1269 {
1270 let v6 = IpHeaders::Ipv6(v6, v6_exts);
1271 assert_eq!(v6, v6.clone());
1272 }
1273 }
1274 }
1275
1276 proptest! {
1277 #[test]
1278 fn ipv4(
1279 v4 in ipv4_any(),
1280 v4_exts in ipv4_extensions_any(),
1281 v6 in ipv6_any(),
1282 v6_exts in ipv6_extensions_any(),
1283 ) {
1284 assert_eq!(
1285 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv4(),
1286 Some((&v4, &v4_exts))
1287 );
1288 assert_eq!(
1289 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv4(),
1290 None
1291 );
1292 }
1293 }
1294
1295 proptest! {
1296 #[test]
1297 fn ipv6(
1298 v4 in ipv4_any(),
1299 v4_exts in ipv4_extensions_any(),
1300 v6 in ipv6_any(),
1301 v6_exts in ipv6_extensions_any(),
1302 ) {
1303 assert_eq!(
1304 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv6(),
1305 None
1306 );
1307 assert_eq!(
1308 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv6(),
1309 Some((&v6, &v6_exts))
1310 );
1311 }
1312 }
1313
1314 proptest! {
1315 #[test]
1316 #[allow(deprecated)]
1317 fn read_from_slice(
1318 v4 in ipv4_any(),
1319 v4_exts in ipv4_extensions_any(),
1320 ) {
1321 let header = combine_v4(&v4, &v4_exts, &[]);
1322 let mut buffer = Vec::with_capacity(header.header_len());
1323 header.write(&mut buffer).unwrap();
1324
1325 let actual = IpHeaders::read_from_slice(&buffer).unwrap();
1326 assert_eq!(actual.0, header);
1327 assert_eq!(actual.1, header.next_header().unwrap());
1328 assert_eq!(actual.2, &buffer[buffer.len()..]);
1329 }
1330 }
1331
1332 proptest! {
1333 #[test]
1334 fn ip_from_slice(
1335 v4 in ipv4_any(),
1336 v4_exts in ipv4_extensions_any(),
1337 v6 in ipv6_any(),
1338 v6_exts in ipv6_extensions_any(),
1339 ) {
1340 use err::ip::{HeadersError::*, HeaderError::*, HeadersSliceError::*};
1341
1342 assert_eq!(
1344 IpHeaders::from_slice(&[]),
1345 Err(Len(err::LenError {
1346 required_len: 1,
1347 len: 0,
1348 len_source: LenSource::Slice,
1349 layer: err::Layer::IpHeader,
1350 layer_start_offset: 0,
1351 }))
1352 );
1353
1354 for version_number in 0..=0xfu8 {
1356 if version_number != 4 && version_number != 6 {
1357 assert_eq!(
1358 IpHeaders::from_slice(&[version_number << 4]),
1359 Err(Content(Ip(UnsupportedIpVersion { version_number })))
1360 );
1361 }
1362 }
1363
1364 let payload = [1,2,3,4];
1365
1366 {
1368 let header = combine_v4(&v4, &v4_exts, &payload);
1369 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1370 header.write(&mut buffer).unwrap();
1371 buffer.extend_from_slice(&payload);
1372 buffer.push(1); {
1376 let actual = IpHeaders::from_slice(&buffer).unwrap();
1377 assert_eq!(&actual.0, &header);
1378 assert_eq!(
1379 actual.1,
1380 IpPayloadSlice{
1381 ip_number: header.next_header().unwrap(),
1382 fragmented: header.is_fragmenting_payload(),
1383 len_source: LenSource::Ipv4HeaderTotalLen,
1384 payload: &payload
1385 }
1386 );
1387 }
1388
1389 IpHeaders::from_slice(&buffer[..1]).unwrap_err();
1391
1392 if v4_exts.header_len() > 0 {
1394 IpHeaders::from_slice(&buffer[..v4.header_len() + 1]).unwrap_err();
1395 }
1396
1397 {
1399 let bad_total_len = (v4.header_len() - 1) as u16;
1400
1401 let mut buffer = buffer.clone();
1402 let bad_total_len_be = bad_total_len.to_be_bytes();
1404 buffer[2] = bad_total_len_be[0];
1405 buffer[3] = bad_total_len_be[1];
1406 assert_eq!(
1407 IpHeaders::from_slice(&buffer[..]).unwrap_err(),
1408 HeadersSliceError::Len(LenError{
1409 required_len: v4.header_len(),
1410 len: bad_total_len as usize,
1411 len_source: LenSource::Ipv4HeaderTotalLen,
1412 layer: Layer::Ipv4Packet,
1413 layer_start_offset: 0,
1414 })
1415 );
1416 }
1417 }
1418
1419 {
1421 let header = combine_v6(&v6, &v6_exts, &payload);
1422 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1423 header.write(&mut buffer).unwrap();
1424 buffer.extend_from_slice(&payload);
1425 buffer.push(1); {
1429 let actual = IpHeaders::from_slice(&buffer).unwrap();
1430 assert_eq!(&actual.0, &header);
1431 assert_eq!(
1432 actual.1,
1433 IpPayloadSlice{
1434 ip_number: header.next_header().unwrap(),
1435 fragmented: header.is_fragmenting_payload(),
1436 len_source: LenSource::Ipv6HeaderPayloadLen,
1437 payload: &payload
1438 }
1439 );
1440 }
1441
1442 IpHeaders::from_slice(&buffer[..1]).unwrap_err();
1444
1445 if v6_exts.header_len() > 0 {
1447 IpHeaders::from_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err();
1448 }
1449
1450 if v6_exts.header_len() > 0 {
1452 let mut buffer = buffer.clone();
1453
1454 buffer[4] = 0;
1456 buffer[5] = 0;
1457
1458 assert!(
1459 IpHeaders::from_slice(
1460 &buffer[..buffer.len() - payload.len() - 2]
1461 ).is_err()
1462 );
1463 }
1464 }
1465 }
1466 }
1467
1468 proptest! {
1469 #[test]
1470 fn from_slice_lax(
1471 v4 in ipv4_any(),
1472 v4_exts in ipv4_extensions_any(),
1473 v6 in ipv6_any(),
1474 v6_exts in ipv6_extensions_any(),
1475 ) {
1476 use err::ip::{HeaderError::*, LaxHeaderSliceError::*};
1477
1478 let payload = [1,2,3,4];
1479
1480 assert_eq!(
1482 IpHeaders::from_slice_lax(&[]),
1483 Err(Len(err::LenError {
1484 required_len: 1,
1485 len: 0,
1486 len_source: LenSource::Slice,
1487 layer: err::Layer::IpHeader,
1488 layer_start_offset: 0,
1489 }))
1490 );
1491
1492 for version_number in 0..=0xfu8 {
1494 if version_number != 4 && version_number != 6 {
1495 assert_eq!(
1496 IpHeaders::from_slice_lax(&[version_number << 4]),
1497 Err(Content(UnsupportedIpVersion { version_number }))
1498 );
1499 }
1500 }
1501
1502 {
1504 let header = combine_v4(&v4, &v4_exts, &payload);
1505 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1506 header.write(&mut buffer).unwrap();
1507 buffer.extend_from_slice(&payload);
1508 buffer.push(1); {
1512 let actual = IpHeaders::from_slice_lax(&buffer).unwrap();
1513 assert_eq!(&actual.0, &header);
1514 assert_eq!(
1515 actual.1,
1516 LaxIpPayloadSlice{
1517 incomplete: false,
1518 ip_number: header.next_header().unwrap(),
1519 fragmented: header.is_fragmenting_payload(),
1520 len_source: LenSource::Ipv4HeaderTotalLen,
1521 payload: &payload
1522 }
1523 );
1524 }
1525
1526 for len in 1..Ipv4Header::MIN_LEN {
1528 assert_eq!(
1529 IpHeaders::from_slice_lax(&buffer[..len]),
1530 Err(Len(err::LenError {
1531 required_len: Ipv4Header::MIN_LEN,
1532 len,
1533 len_source: LenSource::Slice,
1534 layer: err::Layer::Ipv4Header,
1535 layer_start_offset: 0,
1536 }))
1537 );
1538 }
1539
1540 {
1542 let mut bad_ihl_buffer = buffer.clone();
1543 for bad_ihl in 0..5 {
1544 bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl;
1545 assert_eq!(
1546 IpHeaders::from_slice_lax(&bad_ihl_buffer),
1547 Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl }))
1548 );
1549 }
1550 }
1551
1552 for short_ihl in 5..usize::from(v4.ihl()) {
1554 assert_eq!(
1555 IpHeaders::from_slice_lax(&buffer[..4*short_ihl]),
1556 Err(Len(err::LenError {
1557 required_len: usize::from(v4.ihl())*4,
1558 len: 4*short_ihl,
1559 len_source: LenSource::Slice,
1560 layer: err::Layer::Ipv4Header,
1561 layer_start_offset: 0,
1562 }))
1563 );
1564 }
1565
1566 for payload_len in 0..payload.len(){
1568 let actual = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap();
1569 assert_eq!(&actual.0, &header);
1570 assert_eq!(
1571 actual.1,
1572 LaxIpPayloadSlice{
1573 incomplete: true,
1574 ip_number: header.next_header().unwrap(),
1575 fragmented: header.is_fragmenting_payload(),
1576 len_source: LenSource::Slice,
1577 payload: &payload[..payload_len]
1578 }
1579 );
1580 }
1581
1582 if v4_exts.header_len() > 0 {
1584 let (_, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + 1]).unwrap();
1585 assert!(stop_err.is_some());
1586 }
1587
1588 if v4_exts.auth.is_some() {
1590 use err::ip_auth::HeaderError::ZeroPayloadLen;
1591 use err::ip_exts::HeadersSliceError::Content;
1592 use err::ip_exts::HeaderError::Ipv4Ext;
1593
1594 let mut errored_buffer = buffer.clone();
1596 errored_buffer[v4.header_len() + 1] = 0;
1599
1600 let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap();
1601
1602 assert_eq!(stop_err, Some((Content(Ipv4Ext(ZeroPayloadLen)), Layer::IpAuthHeader)));
1603 }
1604
1605 {
1607 let bad_total_len = (v4.header_len() - 1) as u16;
1608
1609 let mut buffer = buffer.clone();
1610 let bad_total_len_be = bad_total_len.to_be_bytes();
1612 buffer[2] = bad_total_len_be[0];
1613 buffer[3] = bad_total_len_be[1];
1614
1615 let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap();
1616
1617 let (v4_header, v4_exts) = header.ipv4().unwrap();
1618 let expected_headers = IpHeaders::Ipv4(
1619 {
1620 let mut expected_v4 = v4_header.clone();
1621 expected_v4.total_len = bad_total_len;
1622 expected_v4
1623 },
1624 v4_exts.clone()
1625 );
1626 assert_eq!(&expected_headers, &actual.0);
1627 assert_eq!(
1628 actual.1,
1629 LaxIpPayloadSlice{
1630 incomplete: false,
1631 ip_number: header.next_header().unwrap(),
1632 fragmented: header.is_fragmenting_payload(),
1633 len_source: LenSource::Slice,
1634 payload: &buffer[v4_header.header_len() + v4_exts.header_len()..],
1635 }
1636 );
1637 }
1638 }
1639
1640 {
1642 let header = combine_v6(&v6, &v6_exts, &payload);
1643 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1644 header.write(&mut buffer).unwrap();
1645 buffer.extend_from_slice(&payload);
1646 buffer.push(1); {
1650 let actual = IpHeaders::from_slice_lax(&buffer).unwrap();
1651 assert_eq!(&actual.0, &header);
1652 assert_eq!(
1653 actual.1,
1654 LaxIpPayloadSlice{
1655 incomplete: false,
1656 ip_number: header.next_header().unwrap(),
1657 fragmented: header.is_fragmenting_payload(),
1658 len_source: LenSource::Ipv6HeaderPayloadLen,
1659 payload: &payload
1660 }
1661 );
1662 }
1663
1664 for len in 1..Ipv6Header::LEN {
1666 assert_eq!(
1667 IpHeaders::from_slice_lax(&buffer[..len]),
1668 Err(Len(err::LenError {
1669 required_len: Ipv6Header::LEN,
1670 len,
1671 len_source: LenSource::Slice,
1672 layer: err::Layer::Ipv6Header,
1673 layer_start_offset: 0,
1674 }))
1675 );
1676 }
1677
1678 if v6_exts.header_len() > 0 {
1680 let (actual, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v6.header_len() + 1]).unwrap();
1681 assert_eq!(&actual.ipv6().as_ref().unwrap().0, &header.ipv6().as_ref().unwrap().0);
1682 assert!(stop_err.is_some());
1683 }
1684
1685 if v6_exts.auth.is_some() {
1687 use err::ip_auth::HeaderError::ZeroPayloadLen;
1688 use err::ip_exts::HeadersSliceError::Content;
1689 use err::ip_exts::HeaderError::Ipv6Ext;
1690 use err::ipv6_exts::HeaderError::IpAuth;
1691
1692 let mut errored_buffer = buffer.clone();
1694 let auth_offset = v6.header_len() +
1695 v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
1696 v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
1697 v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) +
1698 v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0);
1700
1701 errored_buffer[auth_offset + 1] = 0;
1704
1705 let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap();
1706 assert_eq!(
1707 stop_err,
1708 Some((Content(Ipv6Ext(IpAuth(ZeroPayloadLen))), Layer::IpAuthHeader))
1709 );
1710 }
1711
1712 for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 {
1714 let actual = IpHeaders::from_slice_lax(&buffer[..len]).unwrap();
1715 assert_eq!(&actual.0, &header);
1716 assert_eq!(
1717 actual.1,
1718 LaxIpPayloadSlice{
1719 incomplete: true,
1720 ip_number: header.next_header().unwrap(),
1721 fragmented: header.is_fragmenting_payload(),
1722 len_source: LenSource::Slice,
1723 payload: &payload[..len - v6.header_len() - v6_exts.header_len()]
1724 }
1725 );
1726 }
1727
1728 {
1730 let mut buffer = buffer.clone();
1731 buffer[4] = 0;
1733 buffer[5] = 0;
1734
1735 let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap();
1736
1737 let (v6_header, v6_exts) = header.ipv6().unwrap();
1738 let expected_headers = IpHeaders::Ipv6(
1739 {
1740 let mut expected_v6 = v6_header.clone();
1741 expected_v6.payload_length = 0;
1742 expected_v6
1743 },
1744 v6_exts.clone()
1745 );
1746 assert_eq!(&expected_headers, &actual.0);
1747 assert_eq!(
1748 actual.1,
1749 LaxIpPayloadSlice{
1750 incomplete: false,
1751 ip_number: header.next_header().unwrap(),
1752 fragmented: header.is_fragmenting_payload(),
1753 len_source: LenSource::Slice,
1754 payload: &buffer[v6_header.header_len() + v6_exts.header_len()..],
1755 }
1756 );
1757 }
1758
1759 }
1760 }
1761 }
1762
1763 proptest! {
1764 #[test]
1765 fn from_ipv4_slice(
1766 v4 in ipv4_any(),
1767 v4_exts in ipv4_extensions_any(),
1768 ) {
1769 let payload = [1,2,3,4];
1770
1771 let header = combine_v4(&v4, &v4_exts, &payload);
1772 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1773 header.write(&mut buffer).unwrap();
1774 buffer.extend_from_slice(&payload);
1775 buffer.push(1); {
1779 let actual = IpHeaders::from_ipv4_slice(&buffer).unwrap();
1780 assert_eq!(&actual.0, &header);
1781 assert_eq!(
1782 actual.1,
1783 IpPayloadSlice{
1784 ip_number: header.next_header().unwrap(),
1785 fragmented: header.is_fragmenting_payload(),
1786 len_source: LenSource::Ipv4HeaderTotalLen,
1787 payload: &payload
1788 }
1789 );
1790 }
1791
1792 IpHeaders::from_ipv4_slice(&buffer[..1]).unwrap_err();
1794
1795 if v4_exts.header_len() > 0 {
1797 IpHeaders::from_ipv4_slice(&buffer[..v4.header_len() + 1]).unwrap_err();
1798 }
1799
1800 {
1802 let bad_total_len = (v4.header_len() - 1) as u16;
1803
1804 let mut buffer = buffer.clone();
1805 let bad_total_len_be = bad_total_len.to_be_bytes();
1807 buffer[2] = bad_total_len_be[0];
1808 buffer[3] = bad_total_len_be[1];
1809 assert_eq!(
1810 IpHeaders::from_ipv4_slice(&buffer[..]).unwrap_err(),
1811 err::ipv4::SliceError::Len(LenError{
1812 required_len: v4.header_len(),
1813 len: bad_total_len as usize,
1814 len_source: LenSource::Ipv4HeaderTotalLen,
1815 layer: Layer::Ipv4Packet,
1816 layer_start_offset: 0,
1817 })
1818 );
1819 }
1820 }
1821 }
1822
1823 proptest! {
1824 #[test]
1825 fn from_ipv4_slice_lax(
1826 v4 in ipv4_any(),
1827 v4_exts in ipv4_extensions_any()
1828 ) {
1829 use err::ip::{LaxHeaderSliceError::*, HeaderError::*};
1830
1831 let payload = [1,2,3,4];
1832
1833 assert_eq!(
1835 IpHeaders::from_ipv4_slice_lax(&[]),
1836 Err(Len(err::LenError {
1837 required_len: 20,
1838 len: 0,
1839 len_source: LenSource::Slice,
1840 layer: err::Layer::Ipv4Header,
1841 layer_start_offset: 0,
1842 }))
1843 );
1844
1845 let header = combine_v4(&v4, &v4_exts, &payload);
1847 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1848 header.write(&mut buffer).unwrap();
1849 buffer.extend_from_slice(&payload);
1850 buffer.push(1); {
1854 let actual = IpHeaders::from_ipv4_slice_lax(&buffer).unwrap();
1855 assert_eq!(&actual.0, &header);
1856 assert_eq!(
1857 actual.1,
1858 LaxIpPayloadSlice{
1859 incomplete: false,
1860 ip_number: header.next_header().unwrap(),
1861 fragmented: header.is_fragmenting_payload(),
1862 len_source: LenSource::Ipv4HeaderTotalLen,
1863 payload: &payload
1864 }
1865 );
1866 }
1867
1868 for len in 1..Ipv4Header::MIN_LEN {
1870 assert_eq!(
1871 IpHeaders::from_ipv4_slice_lax(&buffer[..len]),
1872 Err(Len(err::LenError {
1873 required_len: Ipv4Header::MIN_LEN,
1874 len,
1875 len_source: LenSource::Slice,
1876 layer: err::Layer::Ipv4Header,
1877 layer_start_offset: 0,
1878 }))
1879 );
1880 }
1881
1882 {
1884 let mut bad_ihl_buffer = buffer.clone();
1885 for bad_ihl in 0..5 {
1886 bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl;
1887 assert_eq!(
1888 IpHeaders::from_ipv4_slice_lax(&bad_ihl_buffer),
1889 Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl }))
1890 );
1891 }
1892 }
1893
1894 for short_ihl in 5..usize::from(v4.ihl()) {
1896 assert_eq!(
1897 IpHeaders::from_ipv4_slice_lax(&buffer[..4*short_ihl]),
1898 Err(Len(err::LenError {
1899 required_len: usize::from(v4.ihl())*4,
1900 len: 4*short_ihl,
1901 len_source: LenSource::Slice,
1902 layer: err::Layer::Ipv4Header,
1903 layer_start_offset: 0,
1904 }))
1905 );
1906 }
1907
1908 for payload_len in 0..payload.len(){
1910 let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap();
1911 assert_eq!(&actual.0, &header);
1912 assert_eq!(
1913 actual.1,
1914 LaxIpPayloadSlice{
1915 incomplete: true,
1916 ip_number: header.next_header().unwrap(),
1917 fragmented: header.is_fragmenting_payload(),
1918 len_source: LenSource::Slice,
1919 payload: &payload[..payload_len]
1920 }
1921 );
1922 }
1923
1924 if v4_exts.header_len() > 0 {
1926 let (actual, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + 1]).unwrap();
1927 assert_eq!(actual.ipv4().unwrap().0, header.ipv4().unwrap().0);
1928 assert!(stop_err.is_some());
1929 }
1930
1931 if v4_exts.auth.is_some() {
1933 use err::ip_auth::HeaderSliceError::Content;
1934 use err::ip_auth::HeaderError::ZeroPayloadLen;
1935
1936 let mut errored_buffer = buffer.clone();
1938 errored_buffer[v4.header_len() + 1] = 0;
1941
1942 let (_, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&errored_buffer).unwrap();
1943 assert_eq!(stop_err, Some(Content(ZeroPayloadLen)));
1944 }
1945
1946 {
1948 let bad_total_len = (v4.header_len() - 1) as u16;
1949
1950 let mut buffer = buffer.clone();
1951 let bad_total_len_be = bad_total_len.to_be_bytes();
1953 buffer[2] = bad_total_len_be[0];
1954 buffer[3] = bad_total_len_be[1];
1955
1956 let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..]).unwrap();
1957
1958 let (v4_header, v4_exts) = header.ipv4().unwrap();
1959 let expected_headers = IpHeaders::Ipv4(
1960 {
1961 let mut expected_v4 = v4_header.clone();
1962 expected_v4.total_len = bad_total_len;
1963 expected_v4
1964 },
1965 v4_exts.clone()
1966 );
1967 assert_eq!(&expected_headers, &actual.0);
1968 assert_eq!(
1969 actual.1,
1970 LaxIpPayloadSlice{
1971 incomplete: false,
1972 ip_number: header.next_header().unwrap(),
1973 fragmented: header.is_fragmenting_payload(),
1974 len_source: LenSource::Slice,
1975 payload: &buffer[v4_header.header_len() + v4_exts.header_len()..],
1976 }
1977 );
1978 }
1979 }
1980 }
1981
1982 proptest! {
1983 #[test]
1984 fn from_ipv6_slice(
1985 v6 in ipv6_any(),
1986 v6_exts in ipv6_extensions_any(),
1987 ) {
1988 let payload = [1,2,3,4];
1989 let header = combine_v6(&v6, &v6_exts, &payload);
1990 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1991 header.write(&mut buffer).unwrap();
1992 buffer.extend_from_slice(&payload);
1993 buffer.push(1); {
1997 let actual = IpHeaders::from_ipv6_slice(&buffer).unwrap();
1998 assert_eq!(&actual.0, &header);
1999 assert_eq!(
2000 actual.1,
2001 IpPayloadSlice{
2002 ip_number: header.next_header().unwrap(),
2003 fragmented: header.is_fragmenting_payload(),
2004 len_source: LenSource::Ipv6HeaderPayloadLen,
2005 payload: &payload
2006 }
2007 );
2008 }
2009
2010 IpHeaders::from_ipv6_slice(&buffer[..1]).unwrap_err();
2012
2013 if v6_exts.header_len() > 0 {
2015 IpHeaders::from_ipv6_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err();
2016 }
2017
2018 if v6_exts.header_len() > 0 {
2020 let mut buffer = buffer.clone();
2021
2022 buffer[4] = 0;
2024 buffer[5] = 0;
2025
2026 assert!(
2027 IpHeaders::from_ipv6_slice(
2028 &buffer[..buffer.len() - payload.len() - 2]
2029 ).is_err()
2030 );
2031 }
2032 }
2033 }
2034
2035 proptest! {
2036 #[test]
2037 fn from_ipv6_slice_lax(
2038 v6 in ipv6_any(),
2039 v6_exts in ipv6_extensions_any(),
2040 bad_version in 0..0xfu8
2041 ) {
2042 use err::ipv6::{HeaderError::*, HeaderSliceError::*};
2043
2044 let payload = [1,2,3,4];
2045
2046 assert_eq!(
2048 IpHeaders::from_ipv6_slice_lax(&[]),
2049 Err(Len(err::LenError {
2050 required_len: Ipv6Header::LEN,
2051 len: 0,
2052 len_source: LenSource::Slice,
2053 layer: err::Layer::Ipv6Header,
2054 layer_start_offset: 0,
2055 }))
2056 );
2057
2058 let header = combine_v6(&v6, &v6_exts, &payload);
2060 let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
2061 header.write(&mut buffer).unwrap();
2062 buffer.extend_from_slice(&payload);
2063 buffer.push(1); if bad_version != 6 {
2067 let mut bad_vers_buffer = buffer.clone();
2068 bad_vers_buffer[0] = (bad_vers_buffer[0] & 0xf) | (bad_version << 4);
2069 assert_eq!(
2070 IpHeaders::from_ipv6_slice_lax(&bad_vers_buffer),
2071 Err(Content(UnexpectedVersion { version_number: bad_version }))
2072 );
2073 }
2074
2075 {
2077 let actual = IpHeaders::from_ipv6_slice_lax(&buffer).unwrap();
2078 assert_eq!(&actual.0, &header);
2079 assert_eq!(
2080 actual.1,
2081 LaxIpPayloadSlice{
2082 incomplete: false,
2083 ip_number: header.next_header().unwrap(),
2084 fragmented: header.is_fragmenting_payload(),
2085 len_source: LenSource::Ipv6HeaderPayloadLen,
2086 payload: &payload
2087 }
2088 );
2089 }
2090
2091 for len in 1..Ipv6Header::LEN {
2093 assert_eq!(
2094 IpHeaders::from_ipv6_slice_lax(&buffer[..len]),
2095 Err(Len(err::LenError {
2096 required_len: Ipv6Header::LEN,
2097 len,
2098 len_source: LenSource::Slice,
2099 layer: err::Layer::Ipv6Header,
2100 layer_start_offset: 0,
2101 }))
2102 );
2103 }
2104
2105 if v6_exts.header_len() > 0 {
2107 let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&buffer[..v6.header_len() + 1]).unwrap();
2108 assert!(err.is_some());
2109 }
2110
2111 if v6_exts.auth.is_some() {
2113 use err::ip_auth::HeaderError::ZeroPayloadLen;
2114 use err::ipv6_exts::{HeaderSliceError::Content, HeaderError::IpAuth};
2115
2116 let mut errored_buffer = buffer.clone();
2118 let auth_offset = v6.header_len() +
2119 v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
2120 v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
2121 v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) +
2122 v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0);
2124
2125 errored_buffer[auth_offset + 1] = 0;
2128 let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&errored_buffer).unwrap();
2129 assert_eq!(err, Some((Content(IpAuth(ZeroPayloadLen)), Layer::IpAuthHeader)));
2130 }
2131
2132 for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 {
2134 let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..len]).unwrap();
2135 assert_eq!(&actual.0, &header);
2136 assert_eq!(
2137 actual.1,
2138 LaxIpPayloadSlice{
2139 incomplete: true,
2140 ip_number: header.next_header().unwrap(),
2141 fragmented: header.is_fragmenting_payload(),
2142 len_source: LenSource::Slice,
2143 payload: &payload[..len - v6.header_len() - v6_exts.header_len()]
2144 }
2145 );
2146 }
2147
2148 {
2150 let mut buffer = buffer.clone();
2151 buffer[4] = 0;
2153 buffer[5] = 0;
2154
2155 let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..]).unwrap();
2156
2157 let (v6_header, v6_exts) = header.ipv6().unwrap();
2158 let expected_headers = IpHeaders::Ipv6(
2159 {
2160 let mut expected_v6 = v6_header.clone();
2161 expected_v6.payload_length = 0;
2162 expected_v6
2163 },
2164 v6_exts.clone()
2165 );
2166 assert_eq!(&expected_headers, &actual.0);
2167 assert_eq!(
2168 actual.1,
2169 LaxIpPayloadSlice{
2170 incomplete: false,
2171 ip_number: header.next_header().unwrap(),
2172 fragmented: header.is_fragmenting_payload(),
2173 len_source: LenSource::Slice,
2174 payload: &buffer[v6_header.header_len() + v6_exts.header_len()..],
2175 }
2176 );
2177 }
2178 }
2179 }
2180
2181 proptest! {
2182 #[test]
2183 fn read(
2184 v4 in ipv4_any(),
2185 v4_exts in ipv4_extensions_any(),
2186 bad_ihl in 0u8..5u8,
2187 v6 in ipv6_any(),
2188 v6_exts in ipv6_extensions_any(),
2189 ) {
2190 use err::ip::{HeadersError::*, HeaderError::*};
2191
2192 {
2194 let mut cursor = Cursor::new(&[]);
2195 assert!(
2196 IpHeaders::read(&mut cursor)
2197 .unwrap_err()
2198 .io()
2199 .is_some()
2200 );
2201 }
2202 {
2204 let mut cursor = Cursor::new(&[0xf << 4]);
2205 assert_eq!(
2206 IpHeaders::read(&mut cursor).unwrap_err().content().unwrap(),
2207 Ip(UnsupportedIpVersion {
2208 version_number: 0xf
2209 })
2210 );
2211 }
2212 {
2214 let header = combine_v4(&v4, &v4_exts, &[]);
2215 let mut buffer = Vec::with_capacity(header.header_len());
2216 header.write(&mut buffer).unwrap();
2217
2218 {
2220 let mut cursor = Cursor::new(&buffer[..]);
2221 let actual = IpHeaders::read(&mut cursor).unwrap();
2222 assert_eq!(actual.0, header);
2223 assert_eq!(actual.1, header.next_header().unwrap());
2224 }
2225
2226 {
2228 let mut buffer = buffer.clone();
2229 buffer[0] = (buffer[0] & 0b1111_0000) | bad_ihl;
2231 let mut cursor = Cursor::new(&buffer[..]);
2232 assert_eq!(
2233 IpHeaders::read(&mut cursor)
2234 .unwrap_err()
2235 .content()
2236 .unwrap(),
2237 Ip(Ipv4HeaderLengthSmallerThanHeader{
2238 ihl: bad_ihl
2239 })
2240 );
2241 }
2242
2243 {
2245 let bad_total_len = (v4.header_len() - 1) as u16;
2246
2247 let mut buffer = buffer.clone();
2248 let bad_total_len_be = bad_total_len.to_be_bytes();
2250 buffer[2] = bad_total_len_be[0];
2251 buffer[3] = bad_total_len_be[1];
2252 let mut cursor = Cursor::new(&buffer[..]);
2253 assert_eq!(
2254 IpHeaders::read(&mut cursor)
2255 .unwrap_err()
2256 .len()
2257 .unwrap(),
2258 LenError{
2259 required_len: v4.header_len(),
2260 len: bad_total_len as usize,
2261 len_source: LenSource::Ipv4HeaderTotalLen,
2262 layer: Layer::Ipv4Packet,
2263 layer_start_offset: 0,
2264 }
2265 );
2266 }
2267
2268 {
2270 let mut cursor = Cursor::new(&buffer[..1]);
2271 assert!(
2272 IpHeaders::read(&mut cursor)
2273 .unwrap_err()
2274 .io()
2275 .is_some()
2276 );
2277 }
2278
2279 if v4_exts.header_len() > 0 {
2281 let mut cursor = Cursor::new(&buffer[..v4.header_len() + 1]);
2282 IpHeaders::read(&mut cursor).unwrap_err();
2283 }
2284
2285 if v4_exts.auth.is_some() {
2287 let bad_total_len = (buffer.len() - 1) as u16;
2288
2289 let mut buffer = buffer.clone();
2290 let bad_total_len_be = bad_total_len.to_be_bytes();
2292 buffer[2] = bad_total_len_be[0];
2293 buffer[3] = bad_total_len_be[1];
2294 let mut cursor = Cursor::new(&buffer[..]);
2295 assert_eq!(
2296 IpHeaders::read(&mut cursor)
2297 .unwrap_err()
2298 .len()
2299 .unwrap(),
2300 LenError{
2301 required_len: buffer.len() - v4.header_len(),
2302 len: bad_total_len as usize - v4.header_len(),
2303 len_source: LenSource::Ipv4HeaderTotalLen,
2304 layer: Layer::IpAuthHeader,
2305 layer_start_offset: v4.header_len(),
2306 }
2307 );
2308 }
2309
2310 if v4_exts.auth.is_some() {
2312 let mut buffer = buffer.clone();
2313 buffer[v4.header_len() + 1] = 0;
2315 let mut cursor = Cursor::new(&buffer[..]);
2316 assert_eq!(
2317 IpHeaders::read(&mut cursor)
2318 .unwrap_err()
2319 .content()
2320 .unwrap(),
2321 HeadersError::Ipv4Ext(
2322 err::ip_auth::HeaderError::ZeroPayloadLen
2323 )
2324 );
2325 }
2326 }
2327
2328 {
2330 let header = combine_v6(&v6, &v6_exts, &[]);
2331 let mut buffer = Vec::with_capacity(header.header_len());
2332 header.write(&mut buffer).unwrap();
2333
2334 {
2336 let mut cursor = Cursor::new(&buffer[..]);
2337 let actual = IpHeaders::read(&mut cursor).unwrap();
2338 assert_eq!(actual.0, header);
2339 assert_eq!(actual.1, header.next_header().unwrap());
2340 }
2341
2342 {
2344 let mut cursor = Cursor::new(&buffer[..1]);
2345 assert!(
2346 IpHeaders::read(&mut cursor).unwrap_err().io().is_some()
2347 );
2348 }
2349
2350 if v6_exts.header_len() > 0 {
2352 let mut cursor = Cursor::new(&buffer[..Ipv6Header::LEN + 1]);
2353 assert!(
2354 IpHeaders::read(&mut cursor).unwrap_err().io().is_some()
2355 );
2356 }
2357
2358 if v6_exts.header_len() > 0 {
2360 let mut buffer = buffer.clone();
2362 let bad_payload_len = (buffer.len() - header.header_len()) as u16;
2363 let bad_payload_len_be = bad_payload_len.to_be_bytes();
2364 buffer[4] = bad_payload_len_be[0];
2365 buffer[5] = bad_payload_len_be[1];
2366 let mut cursor = Cursor::new(&buffer[..]);
2368 assert!(
2369 IpHeaders::read(&mut cursor).unwrap_err().len().is_some()
2370 );
2371 }
2372
2373 if let Some(auth) = v6_exts.auth.as_ref() {
2375 if v6_exts.routing.is_none() {
2377 let mut buffer = buffer.clone();
2379 let auth_offset = buffer.len() - auth.header_len();
2380 buffer[auth_offset + 1] = 0;
2381 let mut cursor = Cursor::new(&buffer[..]);
2382 assert_eq!(
2383 IpHeaders::read(&mut cursor)
2384 .unwrap_err()
2385 .content()
2386 .unwrap(),
2387 HeadersError::Ipv6Ext(err::ipv6_exts::HeaderError::IpAuth(
2388 err::ip_auth::HeaderError::ZeroPayloadLen
2389 ))
2390 );
2391 }
2392 }
2393 }
2394 }
2395 }
2396
2397 proptest! {
2398 #[test]
2399 fn write(
2400 v4 in ipv4_any(),
2401 v4_exts in ipv4_extensions_any(),
2402 v6 in ipv6_any(),
2403 v6_exts in ipv6_extensions_any(),
2404 ) {
2405 {
2407 let header = combine_v4(&v4, &v4_exts, &[]);
2408 let mut buffer = Vec::with_capacity(header.header_len());
2409 header.write(&mut buffer).unwrap();
2410
2411 let actual = IpHeaders::from_slice(&buffer).unwrap().0;
2412 assert_eq!(header, actual);
2413
2414 {
2416 let mut buffer = [0u8;1];
2417 let mut cursor = Cursor::new(&mut buffer[..]);
2418 assert!(
2419 header.write(&mut cursor)
2420 .unwrap_err()
2421 .io()
2422 .is_some()
2423 );
2424 }
2425
2426 if v4_exts.header_len() > 0 {
2428 let mut buffer = [0u8;Ipv4Header::MAX_LEN + 1];
2429 let mut cursor = Cursor::new(&mut buffer[..v4.header_len() + 1]);
2430 assert!(
2431 header.write(&mut cursor)
2432 .unwrap_err()
2433 .io()
2434 .is_some()
2435 );
2436 }
2437
2438 if v4_exts.header_len() > 0 {
2440 let header = IpHeaders::Ipv4(
2442 {
2443 let mut v4 = v4.clone();
2444 v4.protocol = ip_number::UDP;
2446 v4.total_len = (v4.header_len() + v4_exts.header_len()) as u16;
2447 v4.header_checksum = v4.calc_header_checksum();
2448 v4
2449 },
2450 v4_exts.clone(),
2451 );
2452 let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN];
2453 let mut cursor = Cursor::new(&mut buffer[..]);
2454 assert!(header.write(&mut cursor).is_err());
2455 }
2456 }
2457
2458 {
2460 let header = combine_v6(&v6, &v6_exts, &[]);
2461
2462 let mut buffer = Vec::with_capacity(header.header_len());
2464 header.write(&mut buffer).unwrap();
2465
2466 let actual = IpHeaders::from_slice(&buffer).unwrap().0;
2467 assert_eq!(header, actual);
2468
2469 {
2471 let mut buffer = [0u8;1];
2472 let mut cursor = Cursor::new(&mut buffer[..]);
2473 assert!(
2474 header.write(&mut cursor)
2475 .unwrap_err()
2476 .io()
2477 .is_some()
2478 );
2479 }
2480
2481 if v6_exts.header_len() > 0 {
2483 let mut buffer = [0u8;Ipv6Header::LEN + 1];
2484 let mut cursor = Cursor::new(&mut buffer[..]);
2485 assert!(
2486 header.write(&mut cursor)
2487 .unwrap_err()
2488 .io()
2489 .is_some()
2490 );
2491 }
2492 if v6_exts.header_len() > 0 {
2494 let header = IpHeaders::Ipv6(
2496 {
2497 let mut v6 = v6.clone();
2498 v6.next_header = ip_number::UDP;
2500 v6.payload_length = v6_exts.header_len() as u16;
2501 v6
2502 },
2503 v6_exts.clone(),
2504 );
2505 let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN];
2506 let mut cursor = Cursor::new(&mut buffer[..]);
2507 assert!(header.write(&mut cursor).is_err());
2508 }
2509 }
2510 }
2511 }
2512
2513 proptest! {
2514 #[test]
2515 fn header_len(
2516 v4 in ipv4_any(),
2517 v4_exts in ipv4_extensions_any(),
2518 v6 in ipv6_any(),
2519 v6_exts in ipv6_extensions_any(),
2520 ) {
2521 assert_eq!(
2522 v4.header_len() + v4_exts.header_len(),
2523 IpHeaders::Ipv4(v4, v4_exts).header_len()
2524 );
2525 assert_eq!(
2526 Ipv6Header::LEN + v6_exts.header_len(),
2527 IpHeaders::Ipv6(v6, v6_exts).header_len()
2528 );
2529 }
2530 }
2531
2532 proptest! {
2533 #[test]
2534 fn next_header(
2535 v4 in ipv4_any(),
2536 v4_exts in ipv4_extensions_any(),
2537 v6 in ipv6_any(),
2538 v6_exts in ipv6_extensions_any(),
2539 post_header in ip_number_any()
2540 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2541 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2542 )
2543 ) {
2544 {
2545 let mut header = v4.clone();
2546 let mut exts = v4_exts.clone();
2547 header.protocol = exts.set_next_headers(post_header);
2548 assert_eq!(
2549 Ok(post_header),
2550 IpHeaders::Ipv4(header, exts).next_header()
2551 );
2552 }
2553 {
2554 let mut header = v6.clone();
2555 let mut exts = v6_exts.clone();
2556 header.next_header = exts.set_next_headers(post_header);
2557 assert_eq!(
2558 Ok(post_header),
2559 IpHeaders::Ipv6(header, exts).next_header()
2560 );
2561 }
2562 }
2563 }
2564
2565 proptest! {
2568 #[test]
2569 fn set_payload_len(
2570 v4 in ipv4_any(),
2571 v4_exts in ipv4_extensions_any(),
2572 v6 in ipv6_any(),
2573 v6_exts in ipv6_extensions_any(),
2574 payload_len in 0usize..10
2575 ) {
2576 {
2578 let mut actual = IpHeaders::Ipv4(
2579 v4.clone(),
2580 v4_exts.clone()
2581 );
2582 actual.set_payload_len(payload_len).unwrap();
2583
2584 assert_eq!(
2585 actual,
2586 IpHeaders::Ipv4(
2587 {
2588 let mut re = v4.clone();
2589 re.set_payload_len(v4_exts.header_len() + payload_len).unwrap();
2590 re
2591 },
2592 v4_exts.clone()
2593 )
2594 );
2595 }
2596 {
2598 let mut actual = IpHeaders::Ipv6(
2599 v6.clone(),
2600 v6_exts.clone()
2601 );
2602 actual.set_payload_len(payload_len).unwrap();
2603
2604 assert_eq!(
2605 actual,
2606 IpHeaders::Ipv6(
2607 {
2608 let mut re = v6.clone();
2609 re.set_payload_length(v6_exts.header_len() + payload_len).unwrap();
2610 re
2611 },
2612 v6_exts.clone()
2613 )
2614 );
2615 }
2616
2617 {
2619 let mut actual = IpHeaders::Ipv4(
2620 v4.clone(),
2621 v4_exts.clone()
2622 );
2623 assert!(actual.set_payload_len(usize::MAX).is_err());
2624 }
2625
2626 {
2628 let mut actual = IpHeaders::Ipv6(
2629 v6.clone(),
2630 v6_exts.clone()
2631 );
2632 assert!(actual.set_payload_len(usize::MAX).is_err());
2633 }
2634 }
2635 }
2636
2637 proptest! {
2638 #[test]
2639 fn is_fragmenting_payload(
2640 v4 in ipv4_any(),
2641 v4_exts in ipv4_extensions_any(),
2642 v6 in ipv6_any(),
2643 v6_exts in ipv6_extensions_any()
2644 ) {
2645 assert_eq!(
2647 v4.is_fragmenting_payload(),
2648 IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).is_fragmenting_payload()
2649 );
2650
2651 assert_eq!(
2653 v6_exts.is_fragmenting_payload(),
2654 IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).is_fragmenting_payload()
2655 );
2656 }
2657 }
2658}