1use crate::{
2 err::{ipv6_exts::*, Layer},
3 *,
4};
5
6#[derive(Clone, Debug, Eq, PartialEq, Default)]
24pub struct Ipv6Extensions {
25 pub hop_by_hop_options: Option<Ipv6RawExtHeader>,
26 pub destination_options: Option<Ipv6RawExtHeader>,
27 pub routing: Option<Ipv6RoutingExtensions>,
28 pub fragment: Option<Ipv6FragmentHeader>,
29 pub auth: Option<IpAuthHeader>,
30}
31
32impl Ipv6Extensions {
33 pub const MIN_LEN: usize = 0;
36
37 pub const MAX_LEN: usize = Ipv6RawExtHeader::MAX_LEN * 2
39 + Ipv6RoutingExtensions::MAX_LEN
40 + Ipv6FragmentHeader::LEN
41 + IpAuthHeader::MAX_LEN;
42
43 pub fn from_slice(
72 start_ip_number: IpNumber,
73 slice: &[u8],
74 ) -> Result<(Ipv6Extensions, IpNumber, &[u8]), err::ipv6_exts::HeaderSliceError> {
75 let mut result: Ipv6Extensions = Default::default();
76 let mut rest = slice;
77 let mut next_header = start_ip_number;
78
79 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
80 use ip_number::*;
81
82 if IPV6_HOP_BY_HOP == next_header {
84 let slice = Ipv6RawExtHeaderSlice::from_slice(rest).map_err(Len)?;
85 rest = &rest[slice.slice().len()..];
86 next_header = slice.next_header();
87 result.hop_by_hop_options = Some(slice.to_header());
88 }
89
90 loop {
91 match next_header {
92 IPV6_HOP_BY_HOP => {
93 return Err(Content(HopByHopNotAtStart));
94 }
95 IPV6_DEST_OPTIONS => {
96 if let Some(ref mut routing) = result.routing {
97 if routing.final_destination_options.is_some() {
100 return Ok((result, next_header, rest));
102 } else {
103 let slice = Ipv6RawExtHeaderSlice::from_slice(rest)
104 .map_err(|err| Len(err.add_offset(slice.len() - rest.len())))?;
105 rest = &rest[slice.slice().len()..];
106 next_header = slice.next_header();
107 routing.final_destination_options = Some(slice.to_header());
108 }
109 } else if result.destination_options.is_some() {
110 return Ok((result, next_header, rest));
112 } else {
113 let slice = Ipv6RawExtHeaderSlice::from_slice(rest)
114 .map_err(|err| Len(err.add_offset(slice.len() - rest.len())))?;
115 rest = &rest[slice.slice().len()..];
116 next_header = slice.next_header();
117 result.destination_options = Some(slice.to_header());
118 }
119 }
120 IPV6_ROUTE => {
121 if result.routing.is_some() {
122 return Ok((result, next_header, rest));
124 } else {
125 let slice = Ipv6RawExtHeaderSlice::from_slice(rest)
126 .map_err(|err| Len(err.add_offset(slice.len() - rest.len())))?;
127 rest = &rest[slice.slice().len()..];
128 next_header = slice.next_header();
129 result.routing = Some(Ipv6RoutingExtensions {
130 routing: slice.to_header(),
131 final_destination_options: None,
132 });
133 }
134 }
135 IPV6_FRAG => {
136 if result.fragment.is_some() {
137 return Ok((result, next_header, rest));
139 } else {
140 let slice = Ipv6FragmentHeaderSlice::from_slice(rest)
141 .map_err(|err| Len(err.add_offset(slice.len() - rest.len())))?;
142 rest = &rest[slice.slice().len()..];
143 next_header = slice.next_header();
144 result.fragment = Some(slice.to_header());
145 }
146 }
147 AUTH => {
148 if result.auth.is_some() {
149 return Ok((result, next_header, rest));
151 } else {
152 let slice = IpAuthHeaderSlice::from_slice(rest).map_err(|err| {
153 use err::ip_auth::HeaderSliceError as I;
154 use err::ipv6_exts::HeaderError as O;
155 match err {
156 I::Len(err) => Len(err.add_offset(slice.len() - rest.len())),
157 I::Content(err) => Content(O::IpAuth(err)),
158 }
159 })?;
160 rest = &rest[slice.slice().len()..];
161 next_header = slice.next_header();
162 result.auth = Some(slice.to_header());
163 }
164 }
165 _ => {
166 return Ok((result, next_header, rest));
168 }
169 }
170 }
171 }
173
174 pub fn from_slice_lax(
186 start_ip_number: IpNumber,
187 slice: &[u8],
188 ) -> (
189 Ipv6Extensions,
190 IpNumber,
191 &[u8],
192 Option<(err::ipv6_exts::HeaderSliceError, err::Layer)>,
193 ) {
194 let mut result: Ipv6Extensions = Default::default();
195 let mut rest = slice;
196 let mut next_header = start_ip_number;
197
198 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
199 use ip_number::*;
200
201 if IPV6_HOP_BY_HOP == next_header {
203 match Ipv6RawExtHeaderSlice::from_slice(rest) {
204 Ok(slice) => {
205 rest = &rest[slice.slice().len()..];
206 next_header = slice.next_header();
207 result.hop_by_hop_options = Some(slice.to_header());
208 }
209 Err(error) => {
210 return (
211 result,
212 next_header,
213 rest,
214 Some((Len(error), Layer::Ipv6HopByHopHeader)),
215 );
216 }
217 }
218 }
219
220 loop {
221 match next_header {
222 IPV6_HOP_BY_HOP => {
223 return (
224 result,
225 next_header,
226 rest,
227 Some((Content(HopByHopNotAtStart), Layer::Ipv6HopByHopHeader)),
228 );
229 }
230 IPV6_DEST_OPTIONS => {
231 if let Some(ref mut routing) = result.routing {
232 if routing.final_destination_options.is_some() {
235 return (result, next_header, rest, None);
237 } else {
238 match Ipv6RawExtHeaderSlice::from_slice(rest) {
239 Ok(slice) => {
240 rest = &rest[slice.slice().len()..];
241 next_header = slice.next_header();
242 routing.final_destination_options = Some(slice.to_header());
243 }
244 Err(err) => {
245 return (
246 result,
247 next_header,
248 rest,
249 Some((
250 Len(err.add_offset(slice.len() - rest.len())),
251 Layer::Ipv6DestOptionsHeader,
252 )),
253 );
254 }
255 }
256 }
257 } else if result.destination_options.is_some() {
258 return (result, next_header, rest, None);
260 } else {
261 match Ipv6RawExtHeaderSlice::from_slice(rest) {
262 Ok(slice) => {
263 rest = &rest[slice.slice().len()..];
264 next_header = slice.next_header();
265 result.destination_options = Some(slice.to_header());
266 }
267 Err(err) => {
268 return (
269 result,
270 next_header,
271 rest,
272 Some((
273 Len(err.add_offset(slice.len() - rest.len())),
274 Layer::Ipv6DestOptionsHeader,
275 )),
276 );
277 }
278 }
279 }
280 }
281 IPV6_ROUTE => {
282 if result.routing.is_some() {
283 return (result, next_header, rest, None);
285 } else {
286 match Ipv6RawExtHeaderSlice::from_slice(rest) {
287 Ok(slice) => {
288 rest = &rest[slice.slice().len()..];
289 next_header = slice.next_header();
290 result.routing = Some(Ipv6RoutingExtensions {
291 routing: slice.to_header(),
292 final_destination_options: None,
293 });
294 }
295 Err(err) => {
296 return (
297 result,
298 next_header,
299 rest,
300 Some((
301 Len(err.add_offset(slice.len() - rest.len())),
302 Layer::Ipv6RouteHeader,
303 )),
304 );
305 }
306 }
307 }
308 }
309 IPV6_FRAG => {
310 if result.fragment.is_some() {
311 return (result, next_header, rest, None);
313 } else {
314 match Ipv6FragmentHeaderSlice::from_slice(rest) {
315 Ok(slice) => {
316 rest = &rest[slice.slice().len()..];
317 next_header = slice.next_header();
318 result.fragment = Some(slice.to_header());
319 }
320 Err(err) => {
321 return (
322 result,
323 next_header,
324 rest,
325 Some((
326 Len(err.add_offset(slice.len() - rest.len())),
327 Layer::Ipv6FragHeader,
328 )),
329 );
330 }
331 }
332 }
333 }
334 AUTH => {
335 if result.auth.is_some() {
336 return (result, next_header, rest, None);
338 } else {
339 match IpAuthHeaderSlice::from_slice(rest) {
340 Ok(slice) => {
341 rest = &rest[slice.slice().len()..];
342 next_header = slice.next_header();
343 result.auth = Some(slice.to_header());
344 }
345 Err(err) => {
346 use err::ip_auth::HeaderSliceError as I;
347 use err::ipv6_exts::HeaderError as O;
348 return (
349 result,
350 next_header,
351 rest,
352 Some((
353 match err {
354 I::Len(err) => {
355 Len(err.add_offset(slice.len() - rest.len()))
356 }
357 I::Content(err) => Content(O::IpAuth(err)),
358 },
359 Layer::IpAuthHeader,
360 )),
361 );
362 }
363 }
364 }
365 }
366 _ => {
367 return (result, next_header, rest, None);
369 }
370 }
371 }
372 }
374
375 #[cfg(feature = "std")]
405 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
406 pub fn read<T: std::io::Read + std::io::Seek + Sized>(
407 reader: &mut T,
408 start_ip_number: IpNumber,
409 ) -> Result<(Ipv6Extensions, IpNumber), err::ipv6_exts::HeaderReadError> {
410 let mut result: Ipv6Extensions = Default::default();
411 let mut next_protocol = start_ip_number;
412
413 use err::ipv6_exts::{HeaderError::*, HeaderReadError::*};
414 use ip_number::*;
415
416 if IPV6_HOP_BY_HOP == next_protocol {
418 let header = Ipv6RawExtHeader::read(reader).map_err(Io)?;
419 next_protocol = header.next_header;
420 result.hop_by_hop_options = Some(header);
421 }
422
423 loop {
424 match next_protocol {
425 IPV6_HOP_BY_HOP => {
426 return Err(Content(HopByHopNotAtStart));
427 }
428 IPV6_DEST_OPTIONS => {
429 if let Some(ref mut routing) = result.routing {
430 if routing.final_destination_options.is_some() {
433 return Ok((result, next_protocol));
435 } else {
436 let header = Ipv6RawExtHeader::read(reader).map_err(Io)?;
437 next_protocol = header.next_header;
438 routing.final_destination_options = Some(header);
439 }
440 } else if result.destination_options.is_some() {
441 return Ok((result, next_protocol));
443 } else {
444 let header = Ipv6RawExtHeader::read(reader).map_err(Io)?;
445 next_protocol = header.next_header;
446 result.destination_options = Some(header);
447 }
448 }
449 IPV6_ROUTE => {
450 if result.routing.is_some() {
451 return Ok((result, next_protocol));
453 } else {
454 let header = Ipv6RawExtHeader::read(reader).map_err(Io)?;
455 next_protocol = header.next_header;
456 result.routing = Some(Ipv6RoutingExtensions {
457 routing: header,
458 final_destination_options: None,
459 });
460 }
461 }
462 IPV6_FRAG => {
463 if result.fragment.is_some() {
464 return Ok((result, next_protocol));
466 } else {
467 let header = Ipv6FragmentHeader::read(reader).map_err(Io)?;
468 next_protocol = header.next_header;
469 result.fragment = Some(header);
470 }
471 }
472 AUTH => {
473 if result.auth.is_some() {
474 return Ok((result, next_protocol));
476 } else {
477 let header = IpAuthHeader::read(reader).map_err(|err| {
478 use err::ip_auth::HeaderReadError as I;
479 match err {
480 I::Io(err) => Io(err),
481 I::Content(err) => Content(IpAuth(err)),
482 }
483 })?;
484 next_protocol = header.next_header;
485 result.auth = Some(header);
486 }
487 }
488 _ => {
489 return Ok((result, next_protocol));
491 }
492 }
493 }
494
495 }
497
498 #[cfg(feature = "std")]
528 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
529 pub fn read_limited<T: std::io::Read + std::io::Seek + Sized>(
530 reader: &mut crate::io::LimitedReader<T>,
531 start_ip_number: IpNumber,
532 ) -> Result<(Ipv6Extensions, IpNumber), HeaderLimitedReadError> {
533 use ip_number::*;
534 use HeaderError::*;
535 use HeaderLimitedReadError::*;
536
537 fn map_limited_err(err: err::io::LimitedReadError) -> HeaderLimitedReadError {
538 use crate::err::io::LimitedReadError as I;
539 match err {
540 I::Io(err) => Io(err),
541 I::Len(err) => Len(err),
542 }
543 }
544
545 let mut result: Ipv6Extensions = Default::default();
547 let mut next_protocol = start_ip_number;
548
549 if IPV6_HOP_BY_HOP == next_protocol {
551 let header = Ipv6RawExtHeader::read_limited(reader).map_err(map_limited_err)?;
552 next_protocol = header.next_header;
553 result.hop_by_hop_options = Some(header);
554 }
555
556 loop {
557 match next_protocol {
558 IPV6_HOP_BY_HOP => {
559 return Err(Content(HopByHopNotAtStart));
560 }
561 IPV6_DEST_OPTIONS => {
562 if let Some(ref mut routing) = result.routing {
563 if routing.final_destination_options.is_some() {
566 return Ok((result, next_protocol));
568 } else {
569 let header =
570 Ipv6RawExtHeader::read_limited(reader).map_err(map_limited_err)?;
571 next_protocol = header.next_header;
572 routing.final_destination_options = Some(header);
573 }
574 } else if result.destination_options.is_some() {
575 return Ok((result, next_protocol));
577 } else {
578 let header =
579 Ipv6RawExtHeader::read_limited(reader).map_err(map_limited_err)?;
580 next_protocol = header.next_header;
581 result.destination_options = Some(header);
582 }
583 }
584 IPV6_ROUTE => {
585 if result.routing.is_some() {
586 return Ok((result, next_protocol));
588 } else {
589 let header =
590 Ipv6RawExtHeader::read_limited(reader).map_err(map_limited_err)?;
591 next_protocol = header.next_header;
592 result.routing = Some(Ipv6RoutingExtensions {
593 routing: header,
594 final_destination_options: None,
595 });
596 }
597 }
598 IPV6_FRAG => {
599 if result.fragment.is_some() {
600 return Ok((result, next_protocol));
602 } else {
603 let header =
604 Ipv6FragmentHeader::read_limited(reader).map_err(map_limited_err)?;
605 next_protocol = header.next_header;
606 result.fragment = Some(header);
607 }
608 }
609 AUTH => {
610 if result.auth.is_some() {
611 return Ok((result, next_protocol));
613 } else {
614 let header = IpAuthHeader::read_limited(reader).map_err(|err| {
615 use err::ip_auth::HeaderLimitedReadError as I;
616 match err {
617 I::Io(err) => Io(err),
618 I::Len(err) => Len(err),
619 I::Content(err) => Content(IpAuth(err)),
620 }
621 })?;
622 next_protocol = header.next_header;
623 result.auth = Some(header);
624 }
625 }
626 _ => {
627 return Ok((result, next_protocol));
629 }
630 }
631 }
632
633 }
635
636 pub(crate) fn write_internal<T: CoreWrite + ?Sized>(
644 &self,
645 writer: &mut T,
646 first_header: IpNumber,
647 ) -> Result<(), WriteError<T::Error, err::ipv6_exts::ExtsWalkError>> {
648 use err::ipv6_exts::ExtsWalkError::*;
649 use ip_number::*;
650
651 struct NeedsWrite {
653 pub hop_by_hop_options: bool,
654 pub destination_options: bool,
655 pub routing: bool,
656 pub fragment: bool,
657 pub auth: bool,
658 pub final_destination_options: bool,
659 }
660
661 let mut needs_write = NeedsWrite {
662 hop_by_hop_options: self.hop_by_hop_options.is_some(),
663 destination_options: self.destination_options.is_some(),
664 routing: self.routing.is_some(),
665 fragment: self.fragment.is_some(),
666 auth: self.auth.is_some(),
667 final_destination_options: if let Some(ref routing) = self.routing {
668 routing.final_destination_options.is_some()
669 } else {
670 false
671 },
672 };
673
674 let mut next_header = first_header;
675 let mut route_written = false;
676
677 if IPV6_HOP_BY_HOP == next_header {
679 let header = &self.hop_by_hop_options.as_ref().unwrap();
680 writer
681 .write_all(&header.to_bytes())
682 .map_err(WriteError::Io)?;
683 next_header = header.next_header;
684 needs_write.hop_by_hop_options = false;
685 }
686
687 loop {
688 match next_header {
689 IPV6_HOP_BY_HOP => {
690 if needs_write.hop_by_hop_options {
698 return Err(WriteError::Content(HopByHopNotAtStart));
700 } else {
701 break;
702 }
703 }
704 IPV6_DEST_OPTIONS => {
705 if route_written {
708 if needs_write.final_destination_options {
709 let header = &self
710 .routing
711 .as_ref()
712 .unwrap()
713 .final_destination_options
714 .as_ref()
715 .unwrap();
716 writer
717 .write_all(&header.to_bytes())
718 .map_err(WriteError::Io)?;
719 next_header = header.next_header;
720 needs_write.final_destination_options = false;
721 } else {
722 break;
723 }
724 } else if needs_write.destination_options {
725 let header = &self.destination_options.as_ref().unwrap();
726 writer
727 .write_all(&header.to_bytes())
728 .map_err(WriteError::Io)?;
729 next_header = header.next_header;
730 needs_write.destination_options = false;
731 } else {
732 break;
733 }
734 }
735 IPV6_ROUTE => {
736 if needs_write.routing {
737 let header = &self.routing.as_ref().unwrap().routing;
738 writer
739 .write_all(&header.to_bytes())
740 .map_err(WriteError::Io)?;
741 next_header = header.next_header;
742 needs_write.routing = false;
743 route_written = true;
745 } else {
746 break;
747 }
748 }
749 IPV6_FRAG => {
750 if needs_write.fragment {
751 let header = &self.fragment.as_ref().unwrap();
752 writer
753 .write_all(&header.to_bytes())
754 .map_err(WriteError::Io)?;
755 next_header = header.next_header;
756 needs_write.fragment = false;
757 } else {
758 break;
759 }
760 }
761 AUTH => {
762 if needs_write.auth {
763 let header = &self.auth.as_ref().unwrap();
764 writer
765 .write_all(&header.to_bytes())
766 .map_err(WriteError::Io)?;
767 next_header = header.next_header;
768 needs_write.auth = false;
769 } else {
770 break;
771 }
772 }
773 _ => {
774 break;
776 }
777 }
778 }
779
780 if needs_write.hop_by_hop_options {
782 Err(WriteError::Content(ExtNotReferenced {
783 missing_ext: IpNumber::IPV6_HEADER_HOP_BY_HOP,
784 }))
785 } else if needs_write.destination_options {
786 Err(WriteError::Content(ExtNotReferenced {
787 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
788 }))
789 } else if needs_write.routing {
790 Err(WriteError::Content(ExtNotReferenced {
791 missing_ext: IpNumber::IPV6_ROUTE_HEADER,
792 }))
793 } else if needs_write.fragment {
794 Err(WriteError::Content(ExtNotReferenced {
795 missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER,
796 }))
797 } else if needs_write.auth {
798 Err(WriteError::Content(ExtNotReferenced {
799 missing_ext: IpNumber::AUTHENTICATION_HEADER,
800 }))
801 } else if needs_write.final_destination_options {
802 Err(WriteError::Content(ExtNotReferenced {
803 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
804 }))
805 } else {
806 Ok(())
807 }
808 }
809
810 #[cfg(feature = "std")]
819 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
820 pub fn write<T: std::io::Write + Sized>(
821 &self,
822 writer: &mut T,
823 first_header: IpNumber,
824 ) -> Result<(), err::ipv6_exts::HeaderWriteError> {
825 self.write_internal(&mut IoWriter(writer), first_header)
826 .map_err(|err| match err {
827 WriteError::Io(err) => err::ipv6_exts::HeaderWriteError::Io(err),
828 WriteError::Content(err) => err::ipv6_exts::HeaderWriteError::Content(err),
829 })
830 }
831
832 pub fn header_len(&self) -> usize {
834 let mut result = 0;
835
836 if let Some(ref header) = self.hop_by_hop_options {
837 result += header.header_len();
838 }
839 if let Some(ref header) = self.destination_options {
840 result += header.header_len();
841 }
842 if let Some(ref header) = self.routing {
843 result += header.routing.header_len();
844 if let Some(ref header) = header.final_destination_options {
845 result += header.header_len();
846 }
847 }
848 if let Some(ref header) = self.fragment {
849 result += header.header_len();
850 }
851 if let Some(ref header) = self.auth {
852 result += header.header_len();
853 }
854
855 result
856 }
857
858 pub fn set_next_headers(&mut self, last_protocol_number: IpNumber) -> IpNumber {
865 use ip_number::*;
866
867 let mut next = last_protocol_number;
868
869 if let Some(ref mut routing) = self.routing {
883 if let Some(ref mut header) = routing.final_destination_options {
884 header.next_header = next;
885 next = IPV6_DEST_OPTIONS;
886 }
887 }
888 if let Some(ref mut header) = self.auth {
889 header.next_header = next;
890 next = AUTH;
891 }
892 if let Some(ref mut header) = self.fragment {
893 header.next_header = next;
894 next = IPV6_FRAG;
895 }
896 if let Some(ref mut routing) = self.routing {
897 routing.routing.next_header = next;
898 next = IPV6_ROUTE;
899 }
900 if let Some(ref mut header) = self.destination_options {
901 header.next_header = next;
902 next = IPV6_DEST_OPTIONS;
903 }
904 if let Some(ref mut header) = self.hop_by_hop_options {
905 header.next_header = next;
906 next = IPV6_HOP_BY_HOP;
907 }
908
909 next
910 }
911
912 pub fn next_header(&self, first_next_header: IpNumber) -> Result<IpNumber, ExtsWalkError> {
915 use ip_number::*;
916 use ExtsWalkError::*;
917
918 struct OutstandingRef {
920 pub hop_by_hop_options: bool,
921 pub destination_options: bool,
922 pub routing: bool,
923 pub fragment: bool,
924 pub auth: bool,
925 pub final_destination_options: bool,
926 }
927
928 let mut outstanding_refs = OutstandingRef {
929 hop_by_hop_options: self.hop_by_hop_options.is_some(),
930 destination_options: self.destination_options.is_some(),
931 routing: self.routing.is_some(),
932 fragment: self.fragment.is_some(),
933 auth: self.auth.is_some(),
934 final_destination_options: if let Some(ref routing) = self.routing {
935 routing.final_destination_options.is_some()
936 } else {
937 false
938 },
939 };
940
941 let mut next = first_next_header;
942 let mut route_refed = false;
943
944 if IPV6_HOP_BY_HOP == next {
946 if let Some(ref header) = self.hop_by_hop_options {
947 next = header.next_header;
948 outstanding_refs.hop_by_hop_options = false;
949 }
950 }
951
952 loop {
953 match next {
954 IPV6_HOP_BY_HOP => {
955 if outstanding_refs.hop_by_hop_options {
963 return Err(HopByHopNotAtStart);
965 } else {
966 break;
967 }
968 }
969 IPV6_DEST_OPTIONS => {
970 if route_refed {
973 if outstanding_refs.final_destination_options {
974 let header = &self
975 .routing
976 .as_ref()
977 .unwrap()
978 .final_destination_options
979 .as_ref()
980 .unwrap();
981 next = header.next_header;
982 outstanding_refs.final_destination_options = false;
983 } else {
984 break;
985 }
986 } else if outstanding_refs.destination_options {
987 let header = &self.destination_options.as_ref().unwrap();
988 next = header.next_header;
989 outstanding_refs.destination_options = false;
990 } else {
991 break;
992 }
993 }
994 IPV6_ROUTE => {
995 if outstanding_refs.routing {
996 let header = &self.routing.as_ref().unwrap().routing;
997 next = header.next_header;
998 outstanding_refs.routing = false;
999 route_refed = true;
1001 } else {
1002 break;
1003 }
1004 }
1005 IPV6_FRAG => {
1006 if outstanding_refs.fragment {
1007 let header = &self.fragment.as_ref().unwrap();
1008 next = header.next_header;
1009 outstanding_refs.fragment = false;
1010 } else {
1011 break;
1012 }
1013 }
1014 AUTH => {
1015 if outstanding_refs.auth {
1016 let header = &self.auth.as_ref().unwrap();
1017 next = header.next_header;
1018 outstanding_refs.auth = false;
1019 } else {
1020 break;
1021 }
1022 }
1023 _ => break,
1024 }
1025 }
1026
1027 if outstanding_refs.hop_by_hop_options {
1029 return Err(ExtNotReferenced {
1030 missing_ext: IpNumber::IPV6_HEADER_HOP_BY_HOP,
1031 });
1032 }
1033 if outstanding_refs.destination_options {
1034 return Err(ExtNotReferenced {
1035 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
1036 });
1037 }
1038 if outstanding_refs.routing {
1039 return Err(ExtNotReferenced {
1040 missing_ext: IpNumber::IPV6_ROUTE_HEADER,
1041 });
1042 }
1043 if outstanding_refs.fragment {
1044 return Err(ExtNotReferenced {
1045 missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER,
1046 });
1047 }
1048 if outstanding_refs.auth {
1049 return Err(ExtNotReferenced {
1050 missing_ext: IpNumber::AUTHENTICATION_HEADER,
1051 });
1052 }
1053 if outstanding_refs.final_destination_options {
1054 return Err(ExtNotReferenced {
1055 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
1056 });
1057 }
1058
1059 Ok(next)
1060 }
1061
1062 #[inline]
1071 pub fn is_fragmenting_payload(&self) -> bool {
1072 if let Some(frag) = self.fragment.as_ref() {
1073 frag.is_fragmenting_payload()
1074 } else {
1075 false
1076 }
1077 }
1078
1079 #[inline]
1081 pub fn is_empty(&self) -> bool {
1082 self.hop_by_hop_options.is_none()
1083 && self.destination_options.is_none()
1084 && self.routing.is_none()
1085 && self.fragment.is_none()
1086 && self.auth.is_none()
1087 }
1088}
1089
1090#[cfg(test)]
1091pub mod ipv6_exts_test_helpers {
1092 use super::*;
1093 use crate::ip_number::*;
1094 use alloc::vec::Vec;
1095
1096 pub const EXTENSION_KNOWN_IP_NUMBERS: [IpNumber; 5] = [
1098 AUTH,
1099 IPV6_DEST_OPTIONS,
1100 IPV6_HOP_BY_HOP,
1101 IPV6_FRAG,
1102 IPV6_ROUTE,
1103 ];
1104
1105 pub struct ExtensionTestPayload {
1108 pub ip_numbers: Vec<IpNumber>,
1109 pub lengths: Vec<usize>,
1110 pub data: Vec<u8>,
1111 }
1112
1113 impl ExtensionTestPayload {
1114 pub fn new(ip_numbers: &[IpNumber], header_sizes: &[u8]) -> ExtensionTestPayload {
1115 assert!(ip_numbers.len() > 1);
1116 assert!(header_sizes.len() > 0);
1117
1118 let mut result = ExtensionTestPayload {
1119 ip_numbers: ip_numbers.to_vec(),
1120 lengths: Vec::with_capacity(ip_numbers.len() - 1),
1121 data: Vec::with_capacity((ip_numbers.len() - 1) * (0xff * 8 + 8)),
1122 };
1123 for i in 0..ip_numbers.len() - 1 {
1124 result.add_payload(
1125 ip_numbers[i],
1126 ip_numbers[i + 1],
1127 header_sizes[i % header_sizes.len()],
1128 )
1129 }
1130 result
1131 }
1132
1133 pub fn slice(&self) -> &[u8] {
1134 &self.data
1135 }
1136
1137 fn add_payload(&mut self, ip_number: IpNumber, next_header: IpNumber, header_ext_len: u8) {
1138 match ip_number {
1139 IPV6_HOP_BY_HOP | IPV6_ROUTE | IPV6_DEST_OPTIONS => {
1140 let mut raw: [u8; 0xff * 8 + 8] = [0; 0xff * 8 + 8];
1142 raw[0] = next_header.0;
1143 raw[1] = header_ext_len;
1144
1145 self.data
1147 .extend_from_slice(&raw[..8 + usize::from(header_ext_len) * 8]);
1148 self.lengths.push(8 + usize::from(header_ext_len) * 8);
1149 }
1150 IPV6_FRAG => {
1151 let mut raw: [u8; 8] = [0; 8];
1153 raw[0] = next_header.0;
1154 raw[1] = 0;
1155
1156 self.data.extend_from_slice(&raw[..8]);
1158 self.lengths.push(8);
1159 }
1160 AUTH => {
1161 let mut raw: [u8; 0xff * 4 + 8] = [0; 0xff * 4 + 8];
1162 raw[0] = next_header.0;
1163 let len = if header_ext_len > 0 {
1166 raw[1] = header_ext_len;
1167 usize::from(header_ext_len) * 4
1168 } else {
1169 raw[1] = 1;
1171 4
1172 } + 8;
1173 self.data.extend_from_slice(&raw[..len]);
1174 self.lengths.push(len);
1175 }
1176 _ => unreachable!(),
1177 }
1178 }
1179
1180 pub fn exts_hop_by_hop_error(&self) -> bool {
1184 struct ReadState {
1185 dest_opt: bool,
1186 routing: bool,
1187 final_dest_opt: bool,
1188 frag: bool,
1189 auth: bool,
1190 }
1191
1192 let mut read = ReadState {
1194 dest_opt: false,
1195 routing: false,
1196 final_dest_opt: false,
1197 frag: false,
1198 auth: false,
1199 };
1200
1201 for i in 0..self.ip_numbers.len() {
1202 match self.ip_numbers[i] {
1203 IPV6_HOP_BY_HOP => {
1204 if i != 0 {
1205 return true;
1206 }
1207 }
1208 IPV6_ROUTE => {
1209 if read.routing {
1210 return false;
1211 } else {
1212 read.routing = true;
1213 }
1214 }
1215 IPV6_DEST_OPTIONS => {
1216 if read.routing {
1218 if read.final_dest_opt {
1220 return false;
1221 } else {
1222 read.final_dest_opt = true;
1223 }
1224 } else {
1225 if read.dest_opt {
1227 return false;
1228 } else {
1229 read.dest_opt = true;
1230 }
1231 }
1232 }
1233 IPV6_FRAG => {
1234 if read.frag {
1235 return false;
1236 } else {
1237 read.frag = true;
1238 }
1239 }
1240 AUTH => {
1241 if read.auth {
1242 return false;
1243 } else {
1244 read.auth = true;
1245 }
1246 }
1247 _ => return false,
1248 }
1249 }
1250 return false;
1251 }
1252
1253 pub fn assert_extensions(
1256 &self,
1257 exts: &Ipv6Extensions,
1258 ) -> (usize, Option<IpNumber>, IpNumber) {
1259 struct ReadState {
1260 hop_by_hop: bool,
1261 dest_opt: bool,
1262 routing: bool,
1263 final_dest_opt: bool,
1264 frag: bool,
1265 auth: bool,
1266 }
1267
1268 let mut read = ReadState {
1270 hop_by_hop: false,
1271 dest_opt: false,
1272 routing: false,
1273 final_dest_opt: false,
1274 frag: false,
1275 auth: false,
1276 };
1277
1278 let mut slice = &self.data[..];
1279 let mut last_decoded = None;
1280 let mut post_header = self.ip_numbers[0];
1281
1282 for i in 0..self.ip_numbers.len() - 1 {
1283 let mut stop = false;
1284 match self.ip_numbers[i] {
1285 IPV6_HOP_BY_HOP => {
1286 assert!(false == read.hop_by_hop);
1287 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1288 assert_eq!(&header, exts.hop_by_hop_options.as_ref().unwrap());
1289 slice = rest;
1290 read.hop_by_hop = true;
1291 last_decoded = Some(IPV6_HOP_BY_HOP);
1292 }
1293 IPV6_ROUTE => {
1294 if read.routing {
1295 stop = true;
1296 } else {
1297 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1298 assert_eq!(&header, &exts.routing.as_ref().unwrap().routing);
1299 slice = rest;
1300 read.routing = true;
1301 last_decoded = Some(IPV6_ROUTE);
1302 }
1303 }
1304 IPV6_DEST_OPTIONS => {
1305 if read.routing {
1307 if read.final_dest_opt {
1309 stop = true;
1310 } else {
1311 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1312 assert_eq!(
1313 &header,
1314 exts.routing
1315 .as_ref()
1316 .unwrap()
1317 .final_destination_options
1318 .as_ref()
1319 .unwrap()
1320 );
1321 slice = rest;
1322 read.final_dest_opt = true;
1323 last_decoded = Some(IPV6_DEST_OPTIONS);
1324 }
1325 } else {
1326 if read.dest_opt {
1328 stop = true;
1329 } else {
1330 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1331 assert_eq!(&header, exts.destination_options.as_ref().unwrap());
1332 slice = rest;
1333 read.dest_opt = true;
1334 last_decoded = Some(IPV6_DEST_OPTIONS);
1335 }
1336 }
1337 }
1338 IPV6_FRAG => {
1339 if read.frag {
1340 stop = true;
1342 } else {
1343 let (header, rest) = Ipv6FragmentHeader::from_slice(slice).unwrap();
1344 assert_eq!(&header, exts.fragment.as_ref().unwrap());
1345 slice = rest;
1346 read.frag = true;
1347 last_decoded = Some(IPV6_FRAG);
1348 }
1349 }
1350 AUTH => {
1351 if read.auth {
1352 stop = true;
1354 } else {
1355 let (header, rest) = IpAuthHeader::from_slice(slice).unwrap();
1356 assert_eq!(&header, exts.auth.as_ref().unwrap());
1357 slice = rest;
1358 read.auth = true;
1359 last_decoded = Some(AUTH);
1360 }
1361 }
1362 _ => {
1363 stop = true;
1365 }
1366 }
1367 if stop {
1368 post_header = self.ip_numbers[i];
1369 break;
1370 } else {
1371 post_header = self.ip_numbers[i + 1];
1372 }
1373 }
1374
1375 if false == read.hop_by_hop {
1377 assert!(exts.hop_by_hop_options.is_none());
1378 }
1379 if false == read.dest_opt {
1380 assert!(exts.destination_options.is_none());
1381 }
1382 if false == read.routing {
1383 assert!(exts.routing.is_none());
1384 } else {
1385 if false == read.final_dest_opt {
1386 assert!(exts
1387 .routing
1388 .as_ref()
1389 .unwrap()
1390 .final_destination_options
1391 .is_none());
1392 }
1393 }
1394 if false == read.frag {
1395 assert!(exts.fragment.is_none());
1396 }
1397 if false == read.auth {
1398 assert!(exts.auth.is_none());
1399 }
1400
1401 (self.data.len() - slice.len(), last_decoded, post_header)
1402 }
1403
1404 pub fn lax_extensions_for_len(
1407 &self,
1408 limiting_len: usize,
1409 ) -> (Ipv6Extensions, IpNumber, &[u8], Option<IpNumber>) {
1410 let mut exts: Ipv6Extensions = Default::default();
1412 let mut post_header = *self.ip_numbers.first().unwrap();
1413 let mut slice = &self.data[..];
1414
1415 for i in 0..self.ip_numbers.len() - 1 {
1416 if self.slice().len() - slice.len() + self.lengths[i] > limiting_len {
1418 return (
1419 exts,
1420 self.ip_numbers[i],
1421 &self.slice()[self.slice().len() - slice.len()..limiting_len],
1422 Some(self.ip_numbers[i]),
1423 );
1424 }
1425
1426 let mut stop = false;
1427 match self.ip_numbers[i] {
1428 IPV6_HOP_BY_HOP => {
1429 assert!(exts.hop_by_hop_options.is_none());
1430 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1431 exts.hop_by_hop_options = Some(header);
1432 slice = rest;
1433 }
1434 IPV6_ROUTE => {
1435 if exts.routing.is_some() {
1436 stop = true;
1437 } else {
1438 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1439 exts.routing = Some(Ipv6RoutingExtensions {
1440 routing: header,
1441 final_destination_options: None,
1442 });
1443 slice = rest;
1444 }
1445 }
1446 IPV6_DEST_OPTIONS => {
1447 if let Some(routing) = exts.routing.as_mut() {
1449 if routing.final_destination_options.is_some() {
1451 stop = true;
1452 } else {
1453 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1454 routing.final_destination_options = Some(header);
1455 slice = rest;
1456 }
1457 } else {
1458 if exts.destination_options.is_some() {
1460 stop = true;
1461 } else {
1462 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1463 exts.destination_options = Some(header);
1464 slice = rest;
1465 }
1466 }
1467 }
1468 IPV6_FRAG => {
1469 if exts.fragment.is_some() {
1470 stop = true;
1472 } else {
1473 let (header, rest) = Ipv6FragmentHeader::from_slice(slice).unwrap();
1474 exts.fragment = Some(header);
1475 slice = rest;
1476 }
1477 }
1478 AUTH => {
1479 if exts.auth.is_some() {
1480 stop = true;
1482 } else {
1483 let (header, rest) = IpAuthHeader::from_slice(slice).unwrap();
1484 exts.auth = Some(header);
1485 slice = rest;
1486 }
1487 }
1488 _ => {
1489 stop = true;
1491 }
1492 }
1493 if stop {
1494 post_header = self.ip_numbers[i];
1495 break;
1496 } else {
1497 post_header = self.ip_numbers[i + 1];
1498 }
1499 }
1500
1501 (
1502 exts,
1503 post_header,
1504 &self.slice()[self.slice().len() - slice.len()..limiting_len],
1505 None,
1506 )
1507 }
1508 }
1509
1510 #[derive(Clone)]
1512 pub struct ExtensionTestHeaders {
1513 pub ip_numbers: Vec<IpNumber>,
1514 pub data: Ipv6Extensions,
1515 }
1516
1517 impl ExtensionTestHeaders {
1518 pub fn new(ip_numbers: &[IpNumber], header_sizes: &[u8]) -> ExtensionTestHeaders {
1519 assert!(ip_numbers.len() > 1);
1520 assert!(header_sizes.len() > 0);
1521
1522 let mut result = ExtensionTestHeaders {
1523 ip_numbers: ip_numbers.to_vec(),
1524 data: Default::default(),
1525 };
1526 for i in 0..ip_numbers.len() - 1 {
1527 let succ = result.add_payload(
1528 ip_numbers[i],
1529 ip_numbers[i + 1],
1530 header_sizes[i % header_sizes.len()],
1531 );
1532 if false == succ {
1533 result.ip_numbers.truncate(i + 1);
1537 break;
1538 }
1539 }
1540 result
1541 }
1542
1543 pub fn introduce_missing_ref(&mut self, new_header: IpNumber) -> IpNumber {
1544 assert!(self.ip_numbers.len() >= 2);
1545
1546 if self.ip_numbers.len() >= 3 {
1548 match self.ip_numbers[self.ip_numbers.len() - 3] {
1549 IPV6_HOP_BY_HOP => {
1550 self.data.hop_by_hop_options.as_mut().unwrap().next_header = new_header;
1551 }
1552 IPV6_DEST_OPTIONS => {
1553 if self.ip_numbers[..self.ip_numbers.len() - 3]
1554 .iter()
1555 .any(|&x| x == IPV6_ROUTE)
1556 {
1557 self.data
1558 .routing
1559 .as_mut()
1560 .unwrap()
1561 .final_destination_options
1562 .as_mut()
1563 .unwrap()
1564 .next_header = new_header;
1565 } else {
1566 self.data.destination_options.as_mut().unwrap().next_header =
1567 new_header;
1568 }
1569 }
1570 IPV6_ROUTE => {
1571 self.data.routing.as_mut().unwrap().routing.next_header = new_header;
1572 }
1573 IPV6_FRAG => {
1574 self.data.fragment.as_mut().unwrap().next_header = new_header;
1575 }
1576 AUTH => {
1577 self.data.auth.as_mut().unwrap().next_header = new_header;
1578 }
1579 _ => unreachable!(),
1580 }
1581 match self.ip_numbers[self.ip_numbers.len() - 2] {
1582 IPV6_HOP_BY_HOP => IpNumber::IPV6_HEADER_HOP_BY_HOP,
1583 IPV6_DEST_OPTIONS => IpNumber::IPV6_DESTINATION_OPTIONS,
1584 IPV6_ROUTE => IpNumber::IPV6_ROUTE_HEADER,
1585 IPV6_FRAG => IpNumber::IPV6_FRAGMENTATION_HEADER,
1586 AUTH => IpNumber::AUTHENTICATION_HEADER,
1587 _ => unreachable!(),
1588 }
1589 } else {
1590 let missing = self.ip_numbers[0];
1592 self.ip_numbers[0] = new_header;
1593 match missing {
1594 IPV6_HOP_BY_HOP => IpNumber::IPV6_HEADER_HOP_BY_HOP,
1595 IPV6_DEST_OPTIONS => IpNumber::IPV6_DESTINATION_OPTIONS,
1596 IPV6_ROUTE => IpNumber::IPV6_ROUTE_HEADER,
1597 IPV6_FRAG => IpNumber::IPV6_FRAGMENTATION_HEADER,
1598 AUTH => IpNumber::AUTHENTICATION_HEADER,
1599 _ => unreachable!(),
1600 }
1601 }
1602 }
1603
1604 fn add_payload(
1605 &mut self,
1606 ip_number: IpNumber,
1607 next_header: IpNumber,
1608 header_ext_len: u8,
1609 ) -> bool {
1610 match ip_number {
1611 IPV6_HOP_BY_HOP | IPV6_ROUTE | IPV6_DEST_OPTIONS => {
1612 use Ipv6RawExtHeader as R;
1613 let payload: [u8; R::MAX_PAYLOAD_LEN] = [0; R::MAX_PAYLOAD_LEN];
1614 let len = usize::from(header_ext_len) * 8 + 6;
1615
1616 let raw = Ipv6RawExtHeader::new_raw(next_header, &payload[..len]).unwrap();
1617 match ip_number {
1618 IPV6_HOP_BY_HOP => {
1619 if self.data.hop_by_hop_options.is_none() {
1620 self.data.hop_by_hop_options = Some(raw);
1621 true
1622 } else {
1623 false
1624 }
1625 }
1626 IPV6_ROUTE => {
1627 if self.data.routing.is_none() {
1628 self.data.routing = Some(Ipv6RoutingExtensions {
1629 routing: raw,
1630 final_destination_options: None,
1631 });
1632 true
1633 } else {
1634 false
1635 }
1636 }
1637 IPV6_DEST_OPTIONS => {
1638 if let Some(ref mut route) = self.data.routing {
1639 if route.final_destination_options.is_none() {
1640 route.final_destination_options = Some(raw);
1641 true
1642 } else {
1643 false
1644 }
1645 } else {
1646 if self.data.destination_options.is_none() {
1648 self.data.destination_options = Some(raw);
1649 true
1650 } else {
1651 false
1652 }
1653 }
1654 }
1655 _ => unreachable!(),
1656 }
1657 }
1658 IPV6_FRAG => {
1659 if self.data.fragment.is_none() {
1660 self.data.fragment = Some(Ipv6FragmentHeader::new(
1661 next_header,
1662 IpFragOffset::ZERO,
1663 true,
1664 123,
1665 ));
1666 true
1667 } else {
1668 false
1669 }
1670 }
1671 AUTH => {
1672 if self.data.auth.is_none() {
1673 use IpAuthHeader as A;
1674
1675 let mut len = usize::from(header_ext_len) * 4;
1676 if len > A::MAX_ICV_LEN {
1677 len = A::MAX_ICV_LEN;
1678 }
1679 let raw_icv: [u8; A::MAX_ICV_LEN] = [0; A::MAX_ICV_LEN];
1680 self.data.auth = Some(
1681 IpAuthHeader::new(next_header, 123, 234, &raw_icv[..len]).unwrap(),
1682 );
1683 true
1684 } else {
1685 false
1686 }
1687 }
1688 _ => unreachable!(),
1689 }
1690 }
1691 }
1692}
1693
1694#[cfg(test)]
1695mod test {
1696 use super::ipv6_exts_test_helpers::*;
1697 use super::*;
1698 use crate::ip_number::*;
1699 use crate::test_gens::*;
1700 use alloc::{borrow::ToOwned, vec::Vec};
1701 use proptest::prelude::*;
1702
1703 proptest! {
1704 #[test]
1705 fn from_slice(
1706 header_size in any::<u8>(),
1707 post_header in ip_number_any()
1708 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1709 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1710 )
1711 ) {
1712 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
1713
1714 {
1716 let some_data = [1,2,3,4];
1717 let actual = Ipv6Extensions::from_slice(post_header, &some_data).unwrap();
1718 assert_eq!(actual.0, Default::default());
1719 assert_eq!(actual.1, post_header);
1720 assert_eq!(actual.2, &some_data);
1721 }
1722
1723 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1725 let e = ExtensionTestPayload::new(
1727 ip_numbers,
1728 header_sizes
1729 );
1730
1731 if e.exts_hop_by_hop_error() {
1732 assert_eq!(
1734 Ipv6Extensions::from_slice(ip_numbers[0], e.slice()).unwrap_err(),
1735 Content(HopByHopNotAtStart)
1736 );
1737 } else {
1738 let (header, next, rest) = Ipv6Extensions::from_slice(ip_numbers[0], e.slice()).unwrap();
1740 let (read_len, last_header, expected_post_header) = e.assert_extensions(&header);
1741 assert_eq!(next, expected_post_header);
1742 assert_eq!(rest, &e.slice()[read_len..]);
1743
1744 {
1746 let mut offset: usize = 0;
1747 for l in &e.lengths {
1748 if offset + l >= read_len {
1749 break;
1750 }
1751 offset += l;
1752 }
1753
1754 assert_eq!(
1755 Ipv6Extensions::from_slice(ip_numbers[0], &e.slice()[..read_len - 1]).unwrap_err(),
1756 Len(err::LenError {
1757 required_len: read_len - offset,
1758 len: read_len - offset - 1,
1759 len_source: LenSource::Slice,
1760 layer: match last_header.unwrap() {
1761 AUTH => err::Layer::IpAuthHeader,
1762 IPV6_FRAG => err::Layer::Ipv6FragHeader,
1763 _ => err::Layer::Ipv6ExtHeader
1764 },
1765 layer_start_offset: offset,
1766 })
1767 );
1768 }
1769 }
1770 }
1771
1772 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1774
1775 run_test(
1777 &[*first_header, post_header],
1778 &[header_size],
1779 );
1780
1781 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1782
1783 run_test(
1785 &[*first_header, *second_header, post_header],
1786 &[header_size],
1787 );
1788
1789 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
1790 run_test(
1792 &[*first_header, *second_header, *third_header, post_header],
1793 &[header_size],
1794 );
1795 }
1796 }
1797 }
1798
1799 {
1801 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
1802 let mut bytes = auth.to_bytes();
1803 bytes[1] = 0;
1805 let actual = Ipv6Extensions::from_slice(AUTH, &bytes).unwrap_err();
1806
1807 use err::ipv6_exts::HeaderError::IpAuth;
1808 use err::ip_auth::HeaderError::ZeroPayloadLen;
1809 assert_eq!(actual, Content(IpAuth(ZeroPayloadLen)));
1810 }
1811 }
1812 }
1813
1814 proptest! {
1815 #[test]
1816 fn from_slice_lax(
1817 header_size in any::<u8>(),
1818 post_header in ip_number_any()
1819 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1820 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1821 )
1822 ) {
1823 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
1824
1825 {
1827 let some_data = [1,2,3,4];
1828 let actual = Ipv6Extensions::from_slice_lax(post_header, &some_data);
1829 assert_eq!(actual.0, Default::default());
1830 assert_eq!(actual.1, post_header);
1831 assert_eq!(actual.2, &some_data);
1832 assert!(actual.3.is_none());
1833 }
1834
1835 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1837 let e = ExtensionTestPayload::new(
1839 ip_numbers,
1840 header_sizes
1841 );
1842
1843 if e.exts_hop_by_hop_error() {
1844 let actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], e.slice());
1846 assert_eq!(actual.3.unwrap(), (Content(HopByHopNotAtStart), Layer::Ipv6HopByHopHeader));
1847 } else {
1848 let norm_actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], e.slice());
1850 let norm_expected = e.lax_extensions_for_len(e.slice().len());
1851 assert_eq!(norm_actual.0, norm_expected.0);
1852 assert_eq!(norm_actual.1, norm_expected.1);
1853 assert_eq!(norm_actual.2, norm_expected.2);
1854 assert!(norm_actual.3.is_none());
1855
1856 if norm_actual.0.header_len() > 0 {
1858
1859 let norm_len = norm_actual.0.header_len();
1860 let actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], &e.slice()[..norm_len - 1]);
1861
1862 let expected = e.lax_extensions_for_len(norm_len - 1);
1863 assert_eq!(actual.0, expected.0);
1864 assert_eq!(actual.1, expected.1);
1865 assert_eq!(actual.2, expected.2);
1866 let len_err = actual.3.unwrap().0.len_error().unwrap().clone();
1867 assert_eq!(len_err.len, norm_len - 1 - expected.0.header_len());
1868 assert_eq!(len_err.len_source, LenSource::Slice);
1869 assert_eq!(
1870 len_err.layer,
1871 match expected.3.unwrap() {
1872 AUTH => err::Layer::IpAuthHeader,
1873 IPV6_FRAG => err::Layer::Ipv6FragHeader,
1874 _ => err::Layer::Ipv6ExtHeader
1875 }
1876 );
1877 assert_eq!(len_err.layer_start_offset, expected.0.header_len());
1878 }
1879 }
1880 }
1881
1882 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1884
1885 run_test(
1887 &[*first_header, post_header],
1888 &[header_size],
1889 );
1890
1891 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1892
1893 run_test(
1895 &[*first_header, *second_header, post_header],
1896 &[header_size],
1897 );
1898
1899 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
1900 run_test(
1902 &[*first_header, *second_header, *third_header, post_header],
1903 &[header_size],
1904 );
1905 }
1906 }
1907 }
1908
1909 {
1911 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
1912 let mut bytes = auth.to_bytes();
1913 bytes[1] = 0;
1915 let actual = Ipv6Extensions::from_slice_lax(AUTH, &bytes);
1916 assert_eq!(0, actual.0.header_len());
1917 assert_eq!(AUTH, actual.1);
1918 assert_eq!(&bytes[..], actual.2);
1919
1920 use err::ipv6_exts::HeaderError::IpAuth;
1921 use err::ip_auth::HeaderError::ZeroPayloadLen;
1922 assert_eq!(actual.3.unwrap(), (Content(IpAuth(ZeroPayloadLen)), Layer::IpAuthHeader));
1923 }
1924 }
1925 }
1926
1927 proptest! {
1928 #[test]
1929 fn read(
1930 header_size in any::<u8>(),
1931 post_header in ip_number_any()
1932 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1933 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1934 )
1935 ) {
1936 use err::ipv6_exts::HeaderError::*;
1937 use std::io::Cursor;
1938
1939 {
1941 let mut cursor = Cursor::new(&[]);
1942 let actual = Ipv6Extensions::read(&mut cursor, post_header).unwrap();
1943 assert_eq!(actual.0, Default::default());
1944 assert_eq!(actual.1, post_header);
1945 assert_eq!(0, cursor.position());
1946 }
1947
1948 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1950 let e = ExtensionTestPayload::new(
1952 ip_numbers,
1953 header_sizes
1954 );
1955 let mut cursor = Cursor::new(e.slice());
1956
1957 if e.exts_hop_by_hop_error() {
1958 assert_eq!(
1960 Ipv6Extensions::read(&mut cursor, ip_numbers[0]).unwrap_err().content_error().unwrap(),
1961 HopByHopNotAtStart
1962 );
1963 } else {
1964 let (header, next) = Ipv6Extensions::read(&mut cursor, ip_numbers[0]).unwrap();
1966 let (read_len, _, expected_post_header) = e.assert_extensions(&header);
1967 assert_eq!(next, expected_post_header);
1968 assert_eq!(cursor.position() as usize, read_len);
1969
1970 {
1972 let mut short_cursor = Cursor::new(&e.slice()[..read_len - 1]);
1973 assert!(
1974 Ipv6Extensions::read(&mut short_cursor, ip_numbers[0])
1975 .unwrap_err()
1976 .io_error()
1977 .is_some()
1978 );
1979 }
1980 }
1981 }
1982
1983 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1985
1986 run_test(
1988 &[*first_header, post_header],
1989 &[header_size],
1990 );
1991
1992 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1993
1994 run_test(
1996 &[*first_header, *second_header, post_header],
1997 &[header_size],
1998 );
1999
2000 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2001 run_test(
2003 &[*first_header, *second_header, *third_header, post_header],
2004 &[header_size],
2005 );
2006 }
2007 }
2008 }
2009
2010 {
2012 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
2013 let mut bytes = auth.to_bytes();
2014 bytes[1] = 0;
2016 let mut cursor = Cursor::new(&bytes[..]);
2017 let actual = Ipv6Extensions::read(&mut cursor, AUTH).unwrap_err();
2018
2019 use err::ipv6_exts::HeaderError::IpAuth;
2020 use err::ip_auth::HeaderError::ZeroPayloadLen;
2021 assert_eq!(actual.content_error().unwrap(), IpAuth(ZeroPayloadLen));
2022 }
2023 }
2024 }
2025
2026 proptest! {
2027 #[test]
2028 fn read_limited(
2029 header_size in any::<u8>(),
2030 post_header in ip_number_any()
2031 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2032 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2033 )
2034 ) {
2035 use err::ipv6_exts::HeaderError::*;
2036 use err::Layer;
2037 use std::io::Cursor;
2038 use crate::io::LimitedReader;
2039
2040 {
2042 let mut reader = LimitedReader::new(
2043 Cursor::new(&[]),
2044 0,
2045 LenSource::Slice,
2046 0,
2047 Layer::Ipv6Header
2048 );
2049 let actual = Ipv6Extensions::read_limited(&mut reader, post_header).unwrap();
2050 assert_eq!(actual.0, Default::default());
2051 assert_eq!(actual.1, post_header);
2052 assert_eq!(0, reader.read_len());
2053 }
2054
2055 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
2057 let e = ExtensionTestPayload::new(
2059 ip_numbers,
2060 header_sizes
2061 );
2062 let mut reader = LimitedReader::new(
2063 Cursor::new(e.slice()),
2064 e.slice().len(),
2065 LenSource::Slice,
2066 0,
2067 Layer::Ipv6Header
2068 );
2069
2070 if e.exts_hop_by_hop_error() {
2071 assert_eq!(
2073 Ipv6Extensions::read_limited(&mut reader, ip_numbers[0]).unwrap_err().content().unwrap(),
2074 HopByHopNotAtStart
2075 );
2076 } else {
2077 let (header, next) = Ipv6Extensions::read_limited(&mut reader, ip_numbers[0]).unwrap();
2079 let (read_len, _, expected_post_header) = e.assert_extensions(&header);
2080 assert_eq!(next, expected_post_header);
2081 assert_eq!(reader.read_len() + reader.layer_offset(), read_len);
2082
2083 {
2085 let mut short_reader = LimitedReader::new(
2086 Cursor::new(&e.slice()[..read_len - 1]),
2087 read_len,
2088 LenSource::Slice,
2089 0,
2090 Layer::Ipv6Header
2091 );
2092
2093 assert!(
2094 Ipv6Extensions::read_limited(&mut short_reader, ip_numbers[0])
2095 .unwrap_err()
2096 .io()
2097 .is_some()
2098 );
2099 }
2100
2101 {
2103 let mut short_reader = LimitedReader::new(
2104 Cursor::new(e.slice()),
2105 read_len - 1,
2106 LenSource::Slice,
2107 0,
2108 Layer::Ipv6Header
2109 );
2110
2111 assert!(
2112 Ipv6Extensions::read_limited(&mut short_reader, ip_numbers[0])
2113 .unwrap_err()
2114 .len()
2115 .is_some()
2116 );
2117 }
2118 }
2119 }
2120
2121 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2123
2124 run_test(
2126 &[*first_header, post_header],
2127 &[header_size],
2128 );
2129
2130 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2131
2132 run_test(
2134 &[*first_header, *second_header, post_header],
2135 &[header_size],
2136 );
2137
2138 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2139 run_test(
2141 &[*first_header, *second_header, *third_header, post_header],
2142 &[header_size],
2143 );
2144 }
2145 }
2146 }
2147
2148 {
2150 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
2151 let mut bytes = auth.to_bytes();
2152 bytes[1] = 0;
2154 let mut reader = LimitedReader::new(
2155 Cursor::new(&bytes[..]),
2156 bytes.len(),
2157 LenSource::Slice,
2158 0,
2159 Layer::Ipv6Header
2160 );
2161 let actual = Ipv6Extensions::read_limited(&mut reader, AUTH).unwrap_err();
2162
2163 use err::ipv6_exts::HeaderError::IpAuth;
2164 use err::ip_auth::HeaderError::ZeroPayloadLen;
2165 assert_eq!(actual.content().unwrap(), IpAuth(ZeroPayloadLen));
2166 }
2167 }
2168 }
2169
2170 proptest! {
2171 #[test]
2172 fn write(
2173 header_size in any::<u8>(),
2174 post_header in ip_number_any()
2175 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2176 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2177 )
2178 ) {
2179 {
2181 let exts : Ipv6Extensions = Default::default();
2182 let mut buffer = Vec::new();
2183 exts.write(&mut buffer, post_header).unwrap();
2184 assert_eq!(0, buffer.len());
2185 }
2186
2187 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8], post_header: IpNumber) {
2189 use std::io::Cursor;
2190 use crate::err::ipv6_exts::ExtsWalkError::*;
2191
2192 let e = ExtensionTestHeaders::new(
2194 ip_numbers,
2195 header_sizes
2196 );
2197
2198 if e.ip_numbers[1..e.ip_numbers.len()-1].iter().any(|&x| x == IPV6_HOP_BY_HOP) {
2199 let mut writer = Vec::with_capacity(e.data.header_len());
2201 assert_eq!(
2202 e.data.write(&mut writer, e.ip_numbers[0]).unwrap_err().content().unwrap(),
2203 &HopByHopNotAtStart
2204 );
2205 } else {
2206 {
2208 let mut writer = Vec::with_capacity(e.data.header_len());
2209 e.data.write(&mut writer, e.ip_numbers[0]).unwrap();
2210
2211 if *e.ip_numbers.last().unwrap() != IPV6_HOP_BY_HOP {
2212 let (read, read_next, _) = Ipv6Extensions::from_slice(
2215 e.ip_numbers[0],
2216 &writer
2217 ).unwrap();
2218 assert_eq!(e.data, read);
2219 assert_eq!(*e.ip_numbers.last().unwrap(), read_next);
2220 }
2221 }
2222
2223 {
2225 let mut buffer = Vec::with_capacity(e.data.header_len() - 1);
2226 buffer.resize(e.data.header_len() - 1, 0);
2227 let mut cursor = Cursor::new(&mut buffer[..]);
2228
2229 let err = e.data.write(
2230 &mut cursor,
2231 e.ip_numbers[0]
2232 ).unwrap_err();
2233
2234 assert!(err.io().is_some());
2235 }
2236
2237 {
2239 use crate::err::ipv6_exts::ExtsWalkError::ExtNotReferenced;
2240
2241 let mut missing_ref = e.clone();
2242 let missing_ext = missing_ref.introduce_missing_ref(post_header);
2243
2244 let mut writer = Vec::with_capacity(e.data.header_len());
2245 let err = missing_ref.data.write(
2246 &mut writer,
2247 missing_ref.ip_numbers[0]
2248 ).unwrap_err();
2249
2250 assert_eq!(
2251 err.content().unwrap(),
2252 &ExtNotReferenced{ missing_ext }
2253 );
2254 }
2255 }
2256 }
2257
2258 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2260
2261 run_test(
2263 &[*first_header, post_header],
2264 &[header_size],
2265 post_header,
2266 );
2267
2268 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2269
2270 run_test(
2272 &[*first_header, *second_header, post_header],
2273 &[header_size],
2274 post_header,
2275 );
2276
2277 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2278 run_test(
2280 &[*first_header, *second_header, *third_header, post_header],
2281 &[header_size],
2282 post_header,
2283 );
2284 }
2285 }
2286 }
2287 }
2288 }
2289
2290 proptest! {
2291 #[test]
2292 fn header_len(
2293 hop_by_hop_options in ipv6_raw_ext_any(),
2294 destination_options in ipv6_raw_ext_any(),
2295 routing in ipv6_raw_ext_any(),
2296 fragment in ipv6_fragment_any(),
2297 auth in ip_auth_any(),
2298 final_destination_options in ipv6_raw_ext_any(),
2299 ) {
2300 {
2302 let exts : Ipv6Extensions = Default::default();
2303 assert_eq!(0, exts.header_len());
2304 }
2305
2306 {
2308 let exts = Ipv6Extensions{
2309 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2310 destination_options: Some(destination_options.clone()),
2311 routing: Some(
2312 Ipv6RoutingExtensions{
2313 routing: routing.clone(),
2314 final_destination_options: Some(final_destination_options.clone()),
2315 }
2316 ),
2317 fragment: Some(fragment.clone()),
2318 auth: Some(auth.clone()),
2319 };
2320 assert_eq!(
2321 exts.header_len(),
2322 (
2323 hop_by_hop_options.header_len() +
2324 destination_options.header_len() +
2325 routing.header_len() +
2326 final_destination_options.header_len() +
2327 fragment.header_len() +
2328 auth.header_len()
2329 )
2330 );
2331 }
2332
2333 {
2335 let exts = Ipv6Extensions{
2336 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2337 destination_options: Some(destination_options.clone()),
2338 routing: Some(
2339 Ipv6RoutingExtensions{
2340 routing: routing.clone(),
2341 final_destination_options: None,
2342 }
2343 ),
2344 fragment: Some(fragment.clone()),
2345 auth: Some(auth.clone()),
2346 };
2347 assert_eq!(
2348 exts.header_len(),
2349 (
2350 hop_by_hop_options.header_len() +
2351 destination_options.header_len() +
2352 routing.header_len() +
2353 fragment.header_len() +
2354 auth.header_len()
2355 )
2356 );
2357 }
2358 }
2359 }
2360
2361 proptest! {
2362 #[test]
2363 fn set_next_headers(
2364 hop_by_hop_options in ipv6_raw_ext_any(),
2365 destination_options in ipv6_raw_ext_any(),
2366 routing in ipv6_raw_ext_any(),
2367 fragment in ipv6_fragment_any(),
2368 auth in ip_auth_any(),
2369 final_destination_options in ipv6_raw_ext_any(),
2370 post_header in ip_number_any()
2371 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2372 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2373 ),
2374 ) {
2375 {
2377 let mut exts : Ipv6Extensions = Default::default();
2378 assert_eq!(post_header, exts.set_next_headers(post_header));
2379 assert!(exts.hop_by_hop_options.is_none());
2380 assert!(exts.destination_options.is_none());
2381 assert!(exts.routing.is_none());
2382 assert!(exts.fragment.is_none());
2383 assert!(exts.auth.is_none());
2384 }
2385
2386 {
2388 let mut exts = Ipv6Extensions{
2389 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2390 destination_options: Some(destination_options.clone()),
2391 routing: Some(
2392 Ipv6RoutingExtensions{
2393 routing: routing.clone(),
2394 final_destination_options: Some(final_destination_options.clone()),
2395 }
2396 ),
2397 fragment: Some(fragment.clone()),
2398 auth: Some(auth.clone()),
2399 };
2400 assert_eq!(IPV6_HOP_BY_HOP, exts.set_next_headers(post_header));
2401
2402 assert_eq!(IPV6_DEST_OPTIONS, exts.hop_by_hop_options.as_ref().unwrap().next_header);
2403 assert_eq!(IPV6_ROUTE, exts.destination_options.as_ref().unwrap().next_header);
2404 assert_eq!(IPV6_FRAG, exts.routing.as_ref().unwrap().routing.next_header);
2405 assert_eq!(AUTH, exts.fragment.as_ref().unwrap().next_header);
2406 assert_eq!(IPV6_DEST_OPTIONS, exts.auth.as_ref().unwrap().next_header);
2407 assert_eq!(post_header, exts.routing.as_ref().unwrap().final_destination_options.as_ref().unwrap().next_header);
2408 }
2409 }
2410 }
2411
2412 proptest! {
2413 #[test]
2414 fn next_header(
2415 header_size in any::<u8>(),
2416 post_header in ip_number_any()
2417 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2418 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2419 ),)
2420 {
2421 {
2423 let exts : Ipv6Extensions = Default::default();
2424 assert_eq!(post_header, exts.next_header(post_header).unwrap());
2425 }
2426
2427 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8], post_header: IpNumber) {
2429 let e = ExtensionTestHeaders::new(
2431 ip_numbers,
2432 header_sizes
2433 );
2434
2435 if e.ip_numbers[1..e.ip_numbers.len()-1].iter().any(|&x| x == IPV6_HOP_BY_HOP) {
2436 use crate::err::ipv6_exts::ExtsWalkError::HopByHopNotAtStart;
2438 assert_eq!(
2439 e.data.next_header(e.ip_numbers[0]).unwrap_err(),
2440 HopByHopNotAtStart
2441 );
2442 } else {
2443 assert_eq!(
2445 *e.ip_numbers.last().unwrap(),
2446 e.data.next_header(e.ip_numbers[0]).unwrap()
2447 );
2448
2449 {
2451 use crate::err::ipv6_exts::ExtsWalkError::ExtNotReferenced;
2452
2453 let mut missing_ref = e.clone();
2454 let missing_ext = missing_ref.introduce_missing_ref(post_header);
2455 assert_eq!(
2456 missing_ref.data.next_header(missing_ref.ip_numbers[0]).unwrap_err(),
2457 ExtNotReferenced{ missing_ext }
2458 );
2459 }
2460 }
2461 }
2462
2463 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2465
2466 run_test(
2468 &[*first_header, post_header],
2469 &[header_size],
2470 post_header,
2471 );
2472
2473 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2474
2475 run_test(
2477 &[*first_header, *second_header, post_header],
2478 &[header_size],
2479 post_header,
2480 );
2481
2482 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2483 run_test(
2485 &[*first_header, *second_header, *third_header, post_header],
2486 &[header_size],
2487 post_header,
2488 );
2489 }
2490 }
2491 }
2492 }
2493 }
2494
2495 #[test]
2496 fn is_fragmenting_payload() {
2497 assert_eq!(
2499 false,
2500 Ipv6Extensions {
2501 hop_by_hop_options: None,
2502 destination_options: None,
2503 routing: None,
2504 fragment: None,
2505 auth: None,
2506 }
2507 .is_fragmenting_payload()
2508 );
2509
2510 assert_eq!(
2512 false,
2513 Ipv6Extensions {
2514 hop_by_hop_options: None,
2515 destination_options: None,
2516 routing: None,
2517 fragment: Some(Ipv6FragmentHeader::new(
2518 ip_number::UDP,
2519 IpFragOffset::ZERO,
2520 false,
2521 0
2522 )),
2523 auth: None,
2524 }
2525 .is_fragmenting_payload()
2526 );
2527
2528 assert!(Ipv6Extensions {
2530 hop_by_hop_options: None,
2531 destination_options: None,
2532 routing: None,
2533 fragment: Some(Ipv6FragmentHeader::new(
2534 ip_number::UDP,
2535 IpFragOffset::ZERO,
2536 true,
2537 0
2538 )),
2539 auth: None,
2540 }
2541 .is_fragmenting_payload());
2542 }
2543
2544 #[test]
2545 fn is_empty() {
2546 assert!(Ipv6Extensions {
2548 hop_by_hop_options: None,
2549 destination_options: None,
2550 routing: None,
2551 fragment: None,
2552 auth: None,
2553 }
2554 .is_empty());
2555
2556 assert_eq!(
2558 false,
2559 Ipv6Extensions {
2560 hop_by_hop_options: Some(
2561 Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6]).unwrap()
2562 ),
2563 destination_options: None,
2564 routing: None,
2565 fragment: None,
2566 auth: None,
2567 }
2568 .is_empty()
2569 );
2570
2571 assert_eq!(
2573 false,
2574 Ipv6Extensions {
2575 hop_by_hop_options: None,
2576 destination_options: Some(
2577 Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6]).unwrap()
2578 ),
2579 routing: None,
2580 fragment: None,
2581 auth: None,
2582 }
2583 .is_empty()
2584 );
2585
2586 assert_eq!(
2588 false,
2589 Ipv6Extensions {
2590 hop_by_hop_options: None,
2591 destination_options: None,
2592 routing: Some(Ipv6RoutingExtensions {
2593 routing: Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6])
2594 .unwrap(),
2595 final_destination_options: None,
2596 }),
2597 fragment: None,
2598 auth: None,
2599 }
2600 .is_empty()
2601 );
2602
2603 assert_eq!(
2605 false,
2606 Ipv6Extensions {
2607 hop_by_hop_options: None,
2608 destination_options: None,
2609 routing: None,
2610 fragment: Some(Ipv6FragmentHeader::new(
2611 ip_number::UDP,
2612 IpFragOffset::ZERO,
2613 true,
2614 0
2615 )),
2616 auth: None,
2617 }
2618 .is_empty()
2619 );
2620
2621 assert_eq!(
2623 false,
2624 Ipv6Extensions {
2625 hop_by_hop_options: None,
2626 destination_options: None,
2627 routing: None,
2628 fragment: None,
2629 auth: Some(IpAuthHeader::new(ip_number::UDP, 0, 0, &[]).unwrap()),
2630 }
2631 .is_empty()
2632 );
2633 }
2634
2635 #[test]
2636 fn debug() {
2637 use alloc::format;
2638
2639 let a: Ipv6Extensions = Default::default();
2640 assert_eq!(
2641 &format!(
2642 "Ipv6Extensions {{ hop_by_hop_options: {:?}, destination_options: {:?}, routing: {:?}, fragment: {:?}, auth: {:?} }}",
2643 a.hop_by_hop_options,
2644 a.destination_options,
2645 a.routing,
2646 a.fragment,
2647 a.auth,
2648 ),
2649 &format!("{:?}", a)
2650 );
2651 }
2652
2653 #[test]
2654 fn clone_eq() {
2655 let a: Ipv6Extensions = Default::default();
2656 assert_eq!(a, a.clone());
2657 }
2658
2659 #[test]
2660 fn default() {
2661 let a: Ipv6Extensions = Default::default();
2662 assert_eq!(a.hop_by_hop_options, None);
2663 assert_eq!(a.destination_options, None);
2664 assert_eq!(a.routing, None);
2665 assert_eq!(a.fragment, None);
2666 assert_eq!(a.auth, None);
2667 }
2668}