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 #[cfg(feature = "std")]
645 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
646 pub fn write<T: std::io::Write + Sized>(
647 &self,
648 writer: &mut T,
649 first_header: IpNumber,
650 ) -> Result<(), err::ipv6_exts::HeaderWriteError> {
651 use err::ipv6_exts::ExtsWalkError::*;
652 use err::ipv6_exts::HeaderWriteError::*;
653 use ip_number::*;
654
655 struct NeedsWrite {
657 pub hop_by_hop_options: bool,
658 pub destination_options: bool,
659 pub routing: bool,
660 pub fragment: bool,
661 pub auth: bool,
662 pub final_destination_options: bool,
663 }
664
665 let mut needs_write = NeedsWrite {
666 hop_by_hop_options: self.hop_by_hop_options.is_some(),
667 destination_options: self.destination_options.is_some(),
668 routing: self.routing.is_some(),
669 fragment: self.fragment.is_some(),
670 auth: self.auth.is_some(),
671 final_destination_options: if let Some(ref routing) = self.routing {
672 routing.final_destination_options.is_some()
673 } else {
674 false
675 },
676 };
677
678 let mut next_header = first_header;
679 let mut route_written = false;
680
681 if IPV6_HOP_BY_HOP == next_header {
683 let header = &self.hop_by_hop_options.as_ref().unwrap();
684 header.write(writer).map_err(Io)?;
685 next_header = header.next_header;
686 needs_write.hop_by_hop_options = false;
687 }
688
689 loop {
690 match next_header {
691 IPV6_HOP_BY_HOP => {
692 if needs_write.hop_by_hop_options {
700 return Err(Content(HopByHopNotAtStart));
702 } else {
703 break;
704 }
705 }
706 IPV6_DEST_OPTIONS => {
707 if route_written {
710 if needs_write.final_destination_options {
711 let header = &self
712 .routing
713 .as_ref()
714 .unwrap()
715 .final_destination_options
716 .as_ref()
717 .unwrap();
718 header.write(writer).map_err(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 header.write(writer).map_err(Io)?;
727 next_header = header.next_header;
728 needs_write.destination_options = false;
729 } else {
730 break;
731 }
732 }
733 IPV6_ROUTE => {
734 if needs_write.routing {
735 let header = &self.routing.as_ref().unwrap().routing;
736 header.write(writer).map_err(Io)?;
737 next_header = header.next_header;
738 needs_write.routing = false;
739 route_written = true;
741 } else {
742 break;
743 }
744 }
745 IPV6_FRAG => {
746 if needs_write.fragment {
747 let header = &self.fragment.as_ref().unwrap();
748 header.write(writer).map_err(Io)?;
749 next_header = header.next_header;
750 needs_write.fragment = false;
751 } else {
752 break;
753 }
754 }
755 AUTH => {
756 if needs_write.auth {
757 let header = &self.auth.as_ref().unwrap();
758 header.write(writer).map_err(Io)?;
759 next_header = header.next_header;
760 needs_write.auth = false;
761 } else {
762 break;
763 }
764 }
765 _ => {
766 break;
768 }
769 }
770 }
771
772 if needs_write.hop_by_hop_options {
774 Err(Content(ExtNotReferenced {
775 missing_ext: IpNumber::IPV6_HEADER_HOP_BY_HOP,
776 }))
777 } else if needs_write.destination_options {
778 Err(Content(ExtNotReferenced {
779 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
780 }))
781 } else if needs_write.routing {
782 Err(Content(ExtNotReferenced {
783 missing_ext: IpNumber::IPV6_ROUTE_HEADER,
784 }))
785 } else if needs_write.fragment {
786 Err(Content(ExtNotReferenced {
787 missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER,
788 }))
789 } else if needs_write.auth {
790 Err(Content(ExtNotReferenced {
791 missing_ext: IpNumber::AUTHENTICATION_HEADER,
792 }))
793 } else if needs_write.final_destination_options {
794 Err(Content(ExtNotReferenced {
795 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
796 }))
797 } else {
798 Ok(())
799 }
800 }
801
802 pub fn header_len(&self) -> usize {
804 let mut result = 0;
805
806 if let Some(ref header) = self.hop_by_hop_options {
807 result += header.header_len();
808 }
809 if let Some(ref header) = self.destination_options {
810 result += header.header_len();
811 }
812 if let Some(ref header) = self.routing {
813 result += header.routing.header_len();
814 if let Some(ref header) = header.final_destination_options {
815 result += header.header_len();
816 }
817 }
818 if let Some(ref header) = self.fragment {
819 result += header.header_len();
820 }
821 if let Some(ref header) = self.auth {
822 result += header.header_len();
823 }
824
825 result
826 }
827
828 pub fn set_next_headers(&mut self, last_protocol_number: IpNumber) -> IpNumber {
835 use ip_number::*;
836
837 let mut next = last_protocol_number;
838
839 if let Some(ref mut routing) = self.routing {
853 if let Some(ref mut header) = routing.final_destination_options {
854 header.next_header = next;
855 next = IPV6_DEST_OPTIONS;
856 }
857 }
858 if let Some(ref mut header) = self.auth {
859 header.next_header = next;
860 next = AUTH;
861 }
862 if let Some(ref mut header) = self.fragment {
863 header.next_header = next;
864 next = IPV6_FRAG;
865 }
866 if let Some(ref mut routing) = self.routing {
867 routing.routing.next_header = next;
868 next = IPV6_ROUTE;
869 }
870 if let Some(ref mut header) = self.destination_options {
871 header.next_header = next;
872 next = IPV6_DEST_OPTIONS;
873 }
874 if let Some(ref mut header) = self.hop_by_hop_options {
875 header.next_header = next;
876 next = IPV6_HOP_BY_HOP;
877 }
878
879 next
880 }
881
882 pub fn next_header(&self, first_next_header: IpNumber) -> Result<IpNumber, ExtsWalkError> {
885 use ip_number::*;
886 use ExtsWalkError::*;
887
888 struct OutstandingRef {
890 pub hop_by_hop_options: bool,
891 pub destination_options: bool,
892 pub routing: bool,
893 pub fragment: bool,
894 pub auth: bool,
895 pub final_destination_options: bool,
896 }
897
898 let mut outstanding_refs = OutstandingRef {
899 hop_by_hop_options: self.hop_by_hop_options.is_some(),
900 destination_options: self.destination_options.is_some(),
901 routing: self.routing.is_some(),
902 fragment: self.fragment.is_some(),
903 auth: self.auth.is_some(),
904 final_destination_options: if let Some(ref routing) = self.routing {
905 routing.final_destination_options.is_some()
906 } else {
907 false
908 },
909 };
910
911 let mut next = first_next_header;
912 let mut route_refed = false;
913
914 if IPV6_HOP_BY_HOP == next {
916 if let Some(ref header) = self.hop_by_hop_options {
917 next = header.next_header;
918 outstanding_refs.hop_by_hop_options = false;
919 }
920 }
921
922 loop {
923 match next {
924 IPV6_HOP_BY_HOP => {
925 if outstanding_refs.hop_by_hop_options {
933 return Err(HopByHopNotAtStart);
935 } else {
936 break;
937 }
938 }
939 IPV6_DEST_OPTIONS => {
940 if route_refed {
943 if outstanding_refs.final_destination_options {
944 let header = &self
945 .routing
946 .as_ref()
947 .unwrap()
948 .final_destination_options
949 .as_ref()
950 .unwrap();
951 next = header.next_header;
952 outstanding_refs.final_destination_options = false;
953 } else {
954 break;
955 }
956 } else if outstanding_refs.destination_options {
957 let header = &self.destination_options.as_ref().unwrap();
958 next = header.next_header;
959 outstanding_refs.destination_options = false;
960 } else {
961 break;
962 }
963 }
964 IPV6_ROUTE => {
965 if outstanding_refs.routing {
966 let header = &self.routing.as_ref().unwrap().routing;
967 next = header.next_header;
968 outstanding_refs.routing = false;
969 route_refed = true;
971 } else {
972 break;
973 }
974 }
975 IPV6_FRAG => {
976 if outstanding_refs.fragment {
977 let header = &self.fragment.as_ref().unwrap();
978 next = header.next_header;
979 outstanding_refs.fragment = false;
980 } else {
981 break;
982 }
983 }
984 AUTH => {
985 if outstanding_refs.auth {
986 let header = &self.auth.as_ref().unwrap();
987 next = header.next_header;
988 outstanding_refs.auth = false;
989 } else {
990 break;
991 }
992 }
993 _ => break,
994 }
995 }
996
997 if outstanding_refs.hop_by_hop_options {
999 return Err(ExtNotReferenced {
1000 missing_ext: IpNumber::IPV6_HEADER_HOP_BY_HOP,
1001 });
1002 }
1003 if outstanding_refs.destination_options {
1004 return Err(ExtNotReferenced {
1005 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
1006 });
1007 }
1008 if outstanding_refs.routing {
1009 return Err(ExtNotReferenced {
1010 missing_ext: IpNumber::IPV6_ROUTE_HEADER,
1011 });
1012 }
1013 if outstanding_refs.fragment {
1014 return Err(ExtNotReferenced {
1015 missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER,
1016 });
1017 }
1018 if outstanding_refs.auth {
1019 return Err(ExtNotReferenced {
1020 missing_ext: IpNumber::AUTHENTICATION_HEADER,
1021 });
1022 }
1023 if outstanding_refs.final_destination_options {
1024 return Err(ExtNotReferenced {
1025 missing_ext: IpNumber::IPV6_DESTINATION_OPTIONS,
1026 });
1027 }
1028
1029 Ok(next)
1030 }
1031
1032 #[inline]
1041 pub fn is_fragmenting_payload(&self) -> bool {
1042 if let Some(frag) = self.fragment.as_ref() {
1043 frag.is_fragmenting_payload()
1044 } else {
1045 false
1046 }
1047 }
1048
1049 #[inline]
1051 pub fn is_empty(&self) -> bool {
1052 self.hop_by_hop_options.is_none()
1053 && self.destination_options.is_none()
1054 && self.routing.is_none()
1055 && self.fragment.is_none()
1056 && self.auth.is_none()
1057 }
1058}
1059
1060#[cfg(test)]
1061pub mod ipv6_exts_test_helpers {
1062 use super::*;
1063 use crate::ip_number::*;
1064 use alloc::vec::Vec;
1065
1066 pub const EXTENSION_KNOWN_IP_NUMBERS: [IpNumber; 5] = [
1068 AUTH,
1069 IPV6_DEST_OPTIONS,
1070 IPV6_HOP_BY_HOP,
1071 IPV6_FRAG,
1072 IPV6_ROUTE,
1073 ];
1074
1075 pub struct ExtensionTestPayload {
1078 pub ip_numbers: Vec<IpNumber>,
1079 pub lengths: Vec<usize>,
1080 pub data: Vec<u8>,
1081 }
1082
1083 impl ExtensionTestPayload {
1084 pub fn new(ip_numbers: &[IpNumber], header_sizes: &[u8]) -> ExtensionTestPayload {
1085 assert!(ip_numbers.len() > 1);
1086 assert!(header_sizes.len() > 0);
1087
1088 let mut result = ExtensionTestPayload {
1089 ip_numbers: ip_numbers.to_vec(),
1090 lengths: Vec::with_capacity(ip_numbers.len() - 1),
1091 data: Vec::with_capacity((ip_numbers.len() - 1) * (0xff * 8 + 8)),
1092 };
1093 for i in 0..ip_numbers.len() - 1 {
1094 result.add_payload(
1095 ip_numbers[i],
1096 ip_numbers[i + 1],
1097 header_sizes[i % header_sizes.len()],
1098 )
1099 }
1100 result
1101 }
1102
1103 pub fn slice(&self) -> &[u8] {
1104 &self.data
1105 }
1106
1107 fn add_payload(&mut self, ip_number: IpNumber, next_header: IpNumber, header_ext_len: u8) {
1108 match ip_number {
1109 IPV6_HOP_BY_HOP | IPV6_ROUTE | IPV6_DEST_OPTIONS => {
1110 let mut raw: [u8; 0xff * 8 + 8] = [0; 0xff * 8 + 8];
1112 raw[0] = next_header.0;
1113 raw[1] = header_ext_len;
1114
1115 self.data
1117 .extend_from_slice(&raw[..8 + usize::from(header_ext_len) * 8]);
1118 self.lengths.push(8 + usize::from(header_ext_len) * 8);
1119 }
1120 IPV6_FRAG => {
1121 let mut raw: [u8; 8] = [0; 8];
1123 raw[0] = next_header.0;
1124 raw[1] = 0;
1125
1126 self.data.extend_from_slice(&raw[..8]);
1128 self.lengths.push(8);
1129 }
1130 AUTH => {
1131 let mut raw: [u8; 0xff * 4 + 8] = [0; 0xff * 4 + 8];
1132 raw[0] = next_header.0;
1133 let len = if header_ext_len > 0 {
1136 raw[1] = header_ext_len;
1137 usize::from(header_ext_len) * 4
1138 } else {
1139 raw[1] = 1;
1141 4
1142 } + 8;
1143 self.data.extend_from_slice(&raw[..len]);
1144 self.lengths.push(len);
1145 }
1146 _ => unreachable!(),
1147 }
1148 }
1149
1150 pub fn exts_hop_by_hop_error(&self) -> bool {
1154 struct ReadState {
1155 dest_opt: bool,
1156 routing: bool,
1157 final_dest_opt: bool,
1158 frag: bool,
1159 auth: bool,
1160 }
1161
1162 let mut read = ReadState {
1164 dest_opt: false,
1165 routing: false,
1166 final_dest_opt: false,
1167 frag: false,
1168 auth: false,
1169 };
1170
1171 for i in 0..self.ip_numbers.len() {
1172 match self.ip_numbers[i] {
1173 IPV6_HOP_BY_HOP => {
1174 if i != 0 {
1175 return true;
1176 }
1177 }
1178 IPV6_ROUTE => {
1179 if read.routing {
1180 return false;
1181 } else {
1182 read.routing = true;
1183 }
1184 }
1185 IPV6_DEST_OPTIONS => {
1186 if read.routing {
1188 if read.final_dest_opt {
1190 return false;
1191 } else {
1192 read.final_dest_opt = true;
1193 }
1194 } else {
1195 if read.dest_opt {
1197 return false;
1198 } else {
1199 read.dest_opt = true;
1200 }
1201 }
1202 }
1203 IPV6_FRAG => {
1204 if read.frag {
1205 return false;
1206 } else {
1207 read.frag = true;
1208 }
1209 }
1210 AUTH => {
1211 if read.auth {
1212 return false;
1213 } else {
1214 read.auth = true;
1215 }
1216 }
1217 _ => return false,
1218 }
1219 }
1220 return false;
1221 }
1222
1223 pub fn assert_extensions(
1226 &self,
1227 exts: &Ipv6Extensions,
1228 ) -> (usize, Option<IpNumber>, IpNumber) {
1229 struct ReadState {
1230 hop_by_hop: bool,
1231 dest_opt: bool,
1232 routing: bool,
1233 final_dest_opt: bool,
1234 frag: bool,
1235 auth: bool,
1236 }
1237
1238 let mut read = ReadState {
1240 hop_by_hop: false,
1241 dest_opt: false,
1242 routing: false,
1243 final_dest_opt: false,
1244 frag: false,
1245 auth: false,
1246 };
1247
1248 let mut slice = &self.data[..];
1249 let mut last_decoded = None;
1250 let mut post_header = self.ip_numbers[0];
1251
1252 for i in 0..self.ip_numbers.len() - 1 {
1253 let mut stop = false;
1254 match self.ip_numbers[i] {
1255 IPV6_HOP_BY_HOP => {
1256 assert!(false == read.hop_by_hop);
1257 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1258 assert_eq!(&header, exts.hop_by_hop_options.as_ref().unwrap());
1259 slice = rest;
1260 read.hop_by_hop = true;
1261 last_decoded = Some(IPV6_HOP_BY_HOP);
1262 }
1263 IPV6_ROUTE => {
1264 if read.routing {
1265 stop = true;
1266 } else {
1267 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1268 assert_eq!(&header, &exts.routing.as_ref().unwrap().routing);
1269 slice = rest;
1270 read.routing = true;
1271 last_decoded = Some(IPV6_ROUTE);
1272 }
1273 }
1274 IPV6_DEST_OPTIONS => {
1275 if read.routing {
1277 if read.final_dest_opt {
1279 stop = true;
1280 } else {
1281 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1282 assert_eq!(
1283 &header,
1284 exts.routing
1285 .as_ref()
1286 .unwrap()
1287 .final_destination_options
1288 .as_ref()
1289 .unwrap()
1290 );
1291 slice = rest;
1292 read.final_dest_opt = true;
1293 last_decoded = Some(IPV6_DEST_OPTIONS);
1294 }
1295 } else {
1296 if read.dest_opt {
1298 stop = true;
1299 } else {
1300 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1301 assert_eq!(&header, exts.destination_options.as_ref().unwrap());
1302 slice = rest;
1303 read.dest_opt = true;
1304 last_decoded = Some(IPV6_DEST_OPTIONS);
1305 }
1306 }
1307 }
1308 IPV6_FRAG => {
1309 if read.frag {
1310 stop = true;
1312 } else {
1313 let (header, rest) = Ipv6FragmentHeader::from_slice(slice).unwrap();
1314 assert_eq!(&header, exts.fragment.as_ref().unwrap());
1315 slice = rest;
1316 read.frag = true;
1317 last_decoded = Some(IPV6_FRAG);
1318 }
1319 }
1320 AUTH => {
1321 if read.auth {
1322 stop = true;
1324 } else {
1325 let (header, rest) = IpAuthHeader::from_slice(slice).unwrap();
1326 assert_eq!(&header, exts.auth.as_ref().unwrap());
1327 slice = rest;
1328 read.auth = true;
1329 last_decoded = Some(AUTH);
1330 }
1331 }
1332 _ => {
1333 stop = true;
1335 }
1336 }
1337 if stop {
1338 post_header = self.ip_numbers[i];
1339 break;
1340 } else {
1341 post_header = self.ip_numbers[i + 1];
1342 }
1343 }
1344
1345 if false == read.hop_by_hop {
1347 assert!(exts.hop_by_hop_options.is_none());
1348 }
1349 if false == read.dest_opt {
1350 assert!(exts.destination_options.is_none());
1351 }
1352 if false == read.routing {
1353 assert!(exts.routing.is_none());
1354 } else {
1355 if false == read.final_dest_opt {
1356 assert!(exts
1357 .routing
1358 .as_ref()
1359 .unwrap()
1360 .final_destination_options
1361 .is_none());
1362 }
1363 }
1364 if false == read.frag {
1365 assert!(exts.fragment.is_none());
1366 }
1367 if false == read.auth {
1368 assert!(exts.auth.is_none());
1369 }
1370
1371 (self.data.len() - slice.len(), last_decoded, post_header)
1372 }
1373
1374 pub fn lax_extensions_for_len(
1377 &self,
1378 limiting_len: usize,
1379 ) -> (Ipv6Extensions, IpNumber, &[u8], Option<IpNumber>) {
1380 let mut exts: Ipv6Extensions = Default::default();
1382 let mut post_header = *self.ip_numbers.first().unwrap();
1383 let mut slice = &self.data[..];
1384
1385 for i in 0..self.ip_numbers.len() - 1 {
1386 if self.slice().len() - slice.len() + self.lengths[i] > limiting_len {
1388 return (
1389 exts,
1390 self.ip_numbers[i],
1391 &self.slice()[self.slice().len() - slice.len()..limiting_len],
1392 Some(self.ip_numbers[i]),
1393 );
1394 }
1395
1396 let mut stop = false;
1397 match self.ip_numbers[i] {
1398 IPV6_HOP_BY_HOP => {
1399 assert!(exts.hop_by_hop_options.is_none());
1400 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1401 exts.hop_by_hop_options = Some(header);
1402 slice = rest;
1403 }
1404 IPV6_ROUTE => {
1405 if exts.routing.is_some() {
1406 stop = true;
1407 } else {
1408 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1409 exts.routing = Some(Ipv6RoutingExtensions {
1410 routing: header,
1411 final_destination_options: None,
1412 });
1413 slice = rest;
1414 }
1415 }
1416 IPV6_DEST_OPTIONS => {
1417 if let Some(routing) = exts.routing.as_mut() {
1419 if routing.final_destination_options.is_some() {
1421 stop = true;
1422 } else {
1423 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1424 routing.final_destination_options = Some(header);
1425 slice = rest;
1426 }
1427 } else {
1428 if exts.destination_options.is_some() {
1430 stop = true;
1431 } else {
1432 let (header, rest) = Ipv6RawExtHeader::from_slice(slice).unwrap();
1433 exts.destination_options = Some(header);
1434 slice = rest;
1435 }
1436 }
1437 }
1438 IPV6_FRAG => {
1439 if exts.fragment.is_some() {
1440 stop = true;
1442 } else {
1443 let (header, rest) = Ipv6FragmentHeader::from_slice(slice).unwrap();
1444 exts.fragment = Some(header);
1445 slice = rest;
1446 }
1447 }
1448 AUTH => {
1449 if exts.auth.is_some() {
1450 stop = true;
1452 } else {
1453 let (header, rest) = IpAuthHeader::from_slice(slice).unwrap();
1454 exts.auth = Some(header);
1455 slice = rest;
1456 }
1457 }
1458 _ => {
1459 stop = true;
1461 }
1462 }
1463 if stop {
1464 post_header = self.ip_numbers[i];
1465 break;
1466 } else {
1467 post_header = self.ip_numbers[i + 1];
1468 }
1469 }
1470
1471 (
1472 exts,
1473 post_header,
1474 &self.slice()[self.slice().len() - slice.len()..limiting_len],
1475 None,
1476 )
1477 }
1478 }
1479
1480 #[derive(Clone)]
1482 pub struct ExtensionTestHeaders {
1483 pub ip_numbers: Vec<IpNumber>,
1484 pub data: Ipv6Extensions,
1485 }
1486
1487 impl ExtensionTestHeaders {
1488 pub fn new(ip_numbers: &[IpNumber], header_sizes: &[u8]) -> ExtensionTestHeaders {
1489 assert!(ip_numbers.len() > 1);
1490 assert!(header_sizes.len() > 0);
1491
1492 let mut result = ExtensionTestHeaders {
1493 ip_numbers: ip_numbers.to_vec(),
1494 data: Default::default(),
1495 };
1496 for i in 0..ip_numbers.len() - 1 {
1497 let succ = result.add_payload(
1498 ip_numbers[i],
1499 ip_numbers[i + 1],
1500 header_sizes[i % header_sizes.len()],
1501 );
1502 if false == succ {
1503 result.ip_numbers.truncate(i + 1);
1507 break;
1508 }
1509 }
1510 result
1511 }
1512
1513 pub fn introduce_missing_ref(&mut self, new_header: IpNumber) -> IpNumber {
1514 assert!(self.ip_numbers.len() >= 2);
1515
1516 if self.ip_numbers.len() >= 3 {
1518 match self.ip_numbers[self.ip_numbers.len() - 3] {
1519 IPV6_HOP_BY_HOP => {
1520 self.data.hop_by_hop_options.as_mut().unwrap().next_header = new_header;
1521 }
1522 IPV6_DEST_OPTIONS => {
1523 if self.ip_numbers[..self.ip_numbers.len() - 3]
1524 .iter()
1525 .any(|&x| x == IPV6_ROUTE)
1526 {
1527 self.data
1528 .routing
1529 .as_mut()
1530 .unwrap()
1531 .final_destination_options
1532 .as_mut()
1533 .unwrap()
1534 .next_header = new_header;
1535 } else {
1536 self.data.destination_options.as_mut().unwrap().next_header =
1537 new_header;
1538 }
1539 }
1540 IPV6_ROUTE => {
1541 self.data.routing.as_mut().unwrap().routing.next_header = new_header;
1542 }
1543 IPV6_FRAG => {
1544 self.data.fragment.as_mut().unwrap().next_header = new_header;
1545 }
1546 AUTH => {
1547 self.data.auth.as_mut().unwrap().next_header = new_header;
1548 }
1549 _ => unreachable!(),
1550 }
1551 match self.ip_numbers[self.ip_numbers.len() - 2] {
1552 IPV6_HOP_BY_HOP => IpNumber::IPV6_HEADER_HOP_BY_HOP,
1553 IPV6_DEST_OPTIONS => IpNumber::IPV6_DESTINATION_OPTIONS,
1554 IPV6_ROUTE => IpNumber::IPV6_ROUTE_HEADER,
1555 IPV6_FRAG => IpNumber::IPV6_FRAGMENTATION_HEADER,
1556 AUTH => IpNumber::AUTHENTICATION_HEADER,
1557 _ => unreachable!(),
1558 }
1559 } else {
1560 let missing = self.ip_numbers[0];
1562 self.ip_numbers[0] = new_header;
1563 match missing {
1564 IPV6_HOP_BY_HOP => IpNumber::IPV6_HEADER_HOP_BY_HOP,
1565 IPV6_DEST_OPTIONS => IpNumber::IPV6_DESTINATION_OPTIONS,
1566 IPV6_ROUTE => IpNumber::IPV6_ROUTE_HEADER,
1567 IPV6_FRAG => IpNumber::IPV6_FRAGMENTATION_HEADER,
1568 AUTH => IpNumber::AUTHENTICATION_HEADER,
1569 _ => unreachable!(),
1570 }
1571 }
1572 }
1573
1574 fn add_payload(
1575 &mut self,
1576 ip_number: IpNumber,
1577 next_header: IpNumber,
1578 header_ext_len: u8,
1579 ) -> bool {
1580 match ip_number {
1581 IPV6_HOP_BY_HOP | IPV6_ROUTE | IPV6_DEST_OPTIONS => {
1582 use Ipv6RawExtHeader as R;
1583 let payload: [u8; R::MAX_PAYLOAD_LEN] = [0; R::MAX_PAYLOAD_LEN];
1584 let len = usize::from(header_ext_len) * 8 + 6;
1585
1586 let raw = Ipv6RawExtHeader::new_raw(next_header, &payload[..len]).unwrap();
1587 match ip_number {
1588 IPV6_HOP_BY_HOP => {
1589 if self.data.hop_by_hop_options.is_none() {
1590 self.data.hop_by_hop_options = Some(raw);
1591 true
1592 } else {
1593 false
1594 }
1595 }
1596 IPV6_ROUTE => {
1597 if self.data.routing.is_none() {
1598 self.data.routing = Some(Ipv6RoutingExtensions {
1599 routing: raw,
1600 final_destination_options: None,
1601 });
1602 true
1603 } else {
1604 false
1605 }
1606 }
1607 IPV6_DEST_OPTIONS => {
1608 if let Some(ref mut route) = self.data.routing {
1609 if route.final_destination_options.is_none() {
1610 route.final_destination_options = Some(raw);
1611 true
1612 } else {
1613 false
1614 }
1615 } else {
1616 if self.data.destination_options.is_none() {
1618 self.data.destination_options = Some(raw);
1619 true
1620 } else {
1621 false
1622 }
1623 }
1624 }
1625 _ => unreachable!(),
1626 }
1627 }
1628 IPV6_FRAG => {
1629 if self.data.fragment.is_none() {
1630 self.data.fragment = Some(Ipv6FragmentHeader::new(
1631 next_header,
1632 IpFragOffset::ZERO,
1633 true,
1634 123,
1635 ));
1636 true
1637 } else {
1638 false
1639 }
1640 }
1641 AUTH => {
1642 if self.data.auth.is_none() {
1643 use IpAuthHeader as A;
1644
1645 let mut len = usize::from(header_ext_len) * 4;
1646 if len > A::MAX_ICV_LEN {
1647 len = A::MAX_ICV_LEN;
1648 }
1649 let raw_icv: [u8; A::MAX_ICV_LEN] = [0; A::MAX_ICV_LEN];
1650 self.data.auth = Some(
1651 IpAuthHeader::new(next_header, 123, 234, &raw_icv[..len]).unwrap(),
1652 );
1653 true
1654 } else {
1655 false
1656 }
1657 }
1658 _ => unreachable!(),
1659 }
1660 }
1661 }
1662}
1663
1664#[cfg(test)]
1665mod test {
1666 use super::ipv6_exts_test_helpers::*;
1667 use super::*;
1668 use crate::ip_number::*;
1669 use crate::test_gens::*;
1670 use alloc::{borrow::ToOwned, vec::Vec};
1671 use proptest::prelude::*;
1672
1673 proptest! {
1674 #[test]
1675 fn from_slice(
1676 header_size in any::<u8>(),
1677 post_header in ip_number_any()
1678 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1679 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1680 )
1681 ) {
1682 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
1683
1684 {
1686 let some_data = [1,2,3,4];
1687 let actual = Ipv6Extensions::from_slice(post_header, &some_data).unwrap();
1688 assert_eq!(actual.0, Default::default());
1689 assert_eq!(actual.1, post_header);
1690 assert_eq!(actual.2, &some_data);
1691 }
1692
1693 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1695 let e = ExtensionTestPayload::new(
1697 ip_numbers,
1698 header_sizes
1699 );
1700
1701 if e.exts_hop_by_hop_error() {
1702 assert_eq!(
1704 Ipv6Extensions::from_slice(ip_numbers[0], e.slice()).unwrap_err(),
1705 Content(HopByHopNotAtStart)
1706 );
1707 } else {
1708 let (header, next, rest) = Ipv6Extensions::from_slice(ip_numbers[0], e.slice()).unwrap();
1710 let (read_len, last_header, expected_post_header) = e.assert_extensions(&header);
1711 assert_eq!(next, expected_post_header);
1712 assert_eq!(rest, &e.slice()[read_len..]);
1713
1714 {
1716 let mut offset: usize = 0;
1717 for l in &e.lengths {
1718 if offset + l >= read_len {
1719 break;
1720 }
1721 offset += l;
1722 }
1723
1724 assert_eq!(
1725 Ipv6Extensions::from_slice(ip_numbers[0], &e.slice()[..read_len - 1]).unwrap_err(),
1726 Len(err::LenError {
1727 required_len: read_len - offset,
1728 len: read_len - offset - 1,
1729 len_source: LenSource::Slice,
1730 layer: match last_header.unwrap() {
1731 AUTH => err::Layer::IpAuthHeader,
1732 IPV6_FRAG => err::Layer::Ipv6FragHeader,
1733 _ => err::Layer::Ipv6ExtHeader
1734 },
1735 layer_start_offset: offset,
1736 })
1737 );
1738 }
1739 }
1740 }
1741
1742 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1744
1745 run_test(
1747 &[*first_header, post_header],
1748 &[header_size],
1749 );
1750
1751 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1752
1753 run_test(
1755 &[*first_header, *second_header, post_header],
1756 &[header_size],
1757 );
1758
1759 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
1760 run_test(
1762 &[*first_header, *second_header, *third_header, post_header],
1763 &[header_size],
1764 );
1765 }
1766 }
1767 }
1768
1769 {
1771 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
1772 let mut bytes = auth.to_bytes();
1773 bytes[1] = 0;
1775 let actual = Ipv6Extensions::from_slice(AUTH, &bytes).unwrap_err();
1776
1777 use err::ipv6_exts::HeaderError::IpAuth;
1778 use err::ip_auth::HeaderError::ZeroPayloadLen;
1779 assert_eq!(actual, Content(IpAuth(ZeroPayloadLen)));
1780 }
1781 }
1782 }
1783
1784 proptest! {
1785 #[test]
1786 fn from_slice_lax(
1787 header_size in any::<u8>(),
1788 post_header in ip_number_any()
1789 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1790 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1791 )
1792 ) {
1793 use err::ipv6_exts::{HeaderError::*, HeaderSliceError::*};
1794
1795 {
1797 let some_data = [1,2,3,4];
1798 let actual = Ipv6Extensions::from_slice_lax(post_header, &some_data);
1799 assert_eq!(actual.0, Default::default());
1800 assert_eq!(actual.1, post_header);
1801 assert_eq!(actual.2, &some_data);
1802 assert!(actual.3.is_none());
1803 }
1804
1805 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1807 let e = ExtensionTestPayload::new(
1809 ip_numbers,
1810 header_sizes
1811 );
1812
1813 if e.exts_hop_by_hop_error() {
1814 let actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], e.slice());
1816 assert_eq!(actual.3.unwrap(), (Content(HopByHopNotAtStart), Layer::Ipv6HopByHopHeader));
1817 } else {
1818 let norm_actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], e.slice());
1820 let norm_expected = e.lax_extensions_for_len(e.slice().len());
1821 assert_eq!(norm_actual.0, norm_expected.0);
1822 assert_eq!(norm_actual.1, norm_expected.1);
1823 assert_eq!(norm_actual.2, norm_expected.2);
1824 assert!(norm_actual.3.is_none());
1825
1826 if norm_actual.0.header_len() > 0 {
1828
1829 let norm_len = norm_actual.0.header_len();
1830 let actual = Ipv6Extensions::from_slice_lax(ip_numbers[0], &e.slice()[..norm_len - 1]);
1831
1832 let expected = e.lax_extensions_for_len(norm_len - 1);
1833 assert_eq!(actual.0, expected.0);
1834 assert_eq!(actual.1, expected.1);
1835 assert_eq!(actual.2, expected.2);
1836 let len_err = actual.3.unwrap().0.len_error().unwrap().clone();
1837 assert_eq!(len_err.len, norm_len - 1 - expected.0.header_len());
1838 assert_eq!(len_err.len_source, LenSource::Slice);
1839 assert_eq!(
1840 len_err.layer,
1841 match expected.3.unwrap() {
1842 AUTH => err::Layer::IpAuthHeader,
1843 IPV6_FRAG => err::Layer::Ipv6FragHeader,
1844 _ => err::Layer::Ipv6ExtHeader
1845 }
1846 );
1847 assert_eq!(len_err.layer_start_offset, expected.0.header_len());
1848 }
1849 }
1850 }
1851
1852 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1854
1855 run_test(
1857 &[*first_header, post_header],
1858 &[header_size],
1859 );
1860
1861 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1862
1863 run_test(
1865 &[*first_header, *second_header, post_header],
1866 &[header_size],
1867 );
1868
1869 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
1870 run_test(
1872 &[*first_header, *second_header, *third_header, post_header],
1873 &[header_size],
1874 );
1875 }
1876 }
1877 }
1878
1879 {
1881 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
1882 let mut bytes = auth.to_bytes();
1883 bytes[1] = 0;
1885 let actual = Ipv6Extensions::from_slice_lax(AUTH, &bytes);
1886 assert_eq!(0, actual.0.header_len());
1887 assert_eq!(AUTH, actual.1);
1888 assert_eq!(&bytes[..], actual.2);
1889
1890 use err::ipv6_exts::HeaderError::IpAuth;
1891 use err::ip_auth::HeaderError::ZeroPayloadLen;
1892 assert_eq!(actual.3.unwrap(), (Content(IpAuth(ZeroPayloadLen)), Layer::IpAuthHeader));
1893 }
1894 }
1895 }
1896
1897 proptest! {
1898 #[test]
1899 fn read(
1900 header_size in any::<u8>(),
1901 post_header in ip_number_any()
1902 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
1903 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
1904 )
1905 ) {
1906 use err::ipv6_exts::HeaderError::*;
1907 use std::io::Cursor;
1908
1909 {
1911 let mut cursor = Cursor::new(&[]);
1912 let actual = Ipv6Extensions::read(&mut cursor, post_header).unwrap();
1913 assert_eq!(actual.0, Default::default());
1914 assert_eq!(actual.1, post_header);
1915 assert_eq!(0, cursor.position());
1916 }
1917
1918 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
1920 let e = ExtensionTestPayload::new(
1922 ip_numbers,
1923 header_sizes
1924 );
1925 let mut cursor = Cursor::new(e.slice());
1926
1927 if e.exts_hop_by_hop_error() {
1928 assert_eq!(
1930 Ipv6Extensions::read(&mut cursor, ip_numbers[0]).unwrap_err().content_error().unwrap(),
1931 HopByHopNotAtStart
1932 );
1933 } else {
1934 let (header, next) = Ipv6Extensions::read(&mut cursor, ip_numbers[0]).unwrap();
1936 let (read_len, _, expected_post_header) = e.assert_extensions(&header);
1937 assert_eq!(next, expected_post_header);
1938 assert_eq!(cursor.position() as usize, read_len);
1939
1940 {
1942 let mut short_cursor = Cursor::new(&e.slice()[..read_len - 1]);
1943 assert!(
1944 Ipv6Extensions::read(&mut short_cursor, ip_numbers[0])
1945 .unwrap_err()
1946 .io_error()
1947 .is_some()
1948 );
1949 }
1950 }
1951 }
1952
1953 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
1955
1956 run_test(
1958 &[*first_header, post_header],
1959 &[header_size],
1960 );
1961
1962 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
1963
1964 run_test(
1966 &[*first_header, *second_header, post_header],
1967 &[header_size],
1968 );
1969
1970 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
1971 run_test(
1973 &[*first_header, *second_header, *third_header, post_header],
1974 &[header_size],
1975 );
1976 }
1977 }
1978 }
1979
1980 {
1982 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
1983 let mut bytes = auth.to_bytes();
1984 bytes[1] = 0;
1986 let mut cursor = Cursor::new(&bytes[..]);
1987 let actual = Ipv6Extensions::read(&mut cursor, AUTH).unwrap_err();
1988
1989 use err::ipv6_exts::HeaderError::IpAuth;
1990 use err::ip_auth::HeaderError::ZeroPayloadLen;
1991 assert_eq!(actual.content_error().unwrap(), IpAuth(ZeroPayloadLen));
1992 }
1993 }
1994 }
1995
1996 proptest! {
1997 #[test]
1998 fn read_limited(
1999 header_size in any::<u8>(),
2000 post_header in ip_number_any()
2001 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2002 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2003 )
2004 ) {
2005 use err::ipv6_exts::HeaderError::*;
2006 use err::Layer;
2007 use std::io::Cursor;
2008 use crate::io::LimitedReader;
2009
2010 {
2012 let mut reader = LimitedReader::new(
2013 Cursor::new(&[]),
2014 0,
2015 LenSource::Slice,
2016 0,
2017 Layer::Ipv6Header
2018 );
2019 let actual = Ipv6Extensions::read_limited(&mut reader, post_header).unwrap();
2020 assert_eq!(actual.0, Default::default());
2021 assert_eq!(actual.1, post_header);
2022 assert_eq!(0, reader.read_len());
2023 }
2024
2025 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
2027 let e = ExtensionTestPayload::new(
2029 ip_numbers,
2030 header_sizes
2031 );
2032 let mut reader = LimitedReader::new(
2033 Cursor::new(e.slice()),
2034 e.slice().len(),
2035 LenSource::Slice,
2036 0,
2037 Layer::Ipv6Header
2038 );
2039
2040 if e.exts_hop_by_hop_error() {
2041 assert_eq!(
2043 Ipv6Extensions::read_limited(&mut reader, ip_numbers[0]).unwrap_err().content().unwrap(),
2044 HopByHopNotAtStart
2045 );
2046 } else {
2047 let (header, next) = Ipv6Extensions::read_limited(&mut reader, ip_numbers[0]).unwrap();
2049 let (read_len, _, expected_post_header) = e.assert_extensions(&header);
2050 assert_eq!(next, expected_post_header);
2051 assert_eq!(reader.read_len() + reader.layer_offset(), read_len);
2052
2053 {
2055 let mut short_reader = LimitedReader::new(
2056 Cursor::new(&e.slice()[..read_len - 1]),
2057 read_len,
2058 LenSource::Slice,
2059 0,
2060 Layer::Ipv6Header
2061 );
2062
2063 assert!(
2064 Ipv6Extensions::read_limited(&mut short_reader, ip_numbers[0])
2065 .unwrap_err()
2066 .io()
2067 .is_some()
2068 );
2069 }
2070
2071 {
2073 let mut short_reader = LimitedReader::new(
2074 Cursor::new(e.slice()),
2075 read_len - 1,
2076 LenSource::Slice,
2077 0,
2078 Layer::Ipv6Header
2079 );
2080
2081 assert!(
2082 Ipv6Extensions::read_limited(&mut short_reader, ip_numbers[0])
2083 .unwrap_err()
2084 .len()
2085 .is_some()
2086 );
2087 }
2088 }
2089 }
2090
2091 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2093
2094 run_test(
2096 &[*first_header, post_header],
2097 &[header_size],
2098 );
2099
2100 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2101
2102 run_test(
2104 &[*first_header, *second_header, post_header],
2105 &[header_size],
2106 );
2107
2108 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2109 run_test(
2111 &[*first_header, *second_header, *third_header, post_header],
2112 &[header_size],
2113 );
2114 }
2115 }
2116 }
2117
2118 {
2120 let auth = IpAuthHeader::new(post_header, 0, 0, &[]).unwrap();
2121 let mut bytes = auth.to_bytes();
2122 bytes[1] = 0;
2124 let mut reader = LimitedReader::new(
2125 Cursor::new(&bytes[..]),
2126 bytes.len(),
2127 LenSource::Slice,
2128 0,
2129 Layer::Ipv6Header
2130 );
2131 let actual = Ipv6Extensions::read_limited(&mut reader, AUTH).unwrap_err();
2132
2133 use err::ipv6_exts::HeaderError::IpAuth;
2134 use err::ip_auth::HeaderError::ZeroPayloadLen;
2135 assert_eq!(actual.content().unwrap(), IpAuth(ZeroPayloadLen));
2136 }
2137 }
2138 }
2139
2140 proptest! {
2141 #[test]
2142 fn write(
2143 header_size in any::<u8>(),
2144 post_header in ip_number_any()
2145 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2146 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2147 )
2148 ) {
2149 {
2151 let exts : Ipv6Extensions = Default::default();
2152 let mut buffer = Vec::new();
2153 exts.write(&mut buffer, post_header).unwrap();
2154 assert_eq!(0, buffer.len());
2155 }
2156
2157 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8], post_header: IpNumber) {
2159 use std::io::Cursor;
2160 use crate::err::ipv6_exts::ExtsWalkError::*;
2161
2162 let e = ExtensionTestHeaders::new(
2164 ip_numbers,
2165 header_sizes
2166 );
2167
2168 if e.ip_numbers[1..e.ip_numbers.len()-1].iter().any(|&x| x == IPV6_HOP_BY_HOP) {
2169 let mut writer = Vec::with_capacity(e.data.header_len());
2171 assert_eq!(
2172 e.data.write(&mut writer, e.ip_numbers[0]).unwrap_err().content().unwrap(),
2173 &HopByHopNotAtStart
2174 );
2175 } else {
2176 {
2178 let mut writer = Vec::with_capacity(e.data.header_len());
2179 e.data.write(&mut writer, e.ip_numbers[0]).unwrap();
2180
2181 if *e.ip_numbers.last().unwrap() != IPV6_HOP_BY_HOP {
2182 let (read, read_next, _) = Ipv6Extensions::from_slice(
2185 e.ip_numbers[0],
2186 &writer
2187 ).unwrap();
2188 assert_eq!(e.data, read);
2189 assert_eq!(*e.ip_numbers.last().unwrap(), read_next);
2190 }
2191 }
2192
2193 {
2195 let mut buffer = Vec::with_capacity(e.data.header_len() - 1);
2196 buffer.resize(e.data.header_len() - 1, 0);
2197 let mut cursor = Cursor::new(&mut buffer[..]);
2198
2199 let err = e.data.write(
2200 &mut cursor,
2201 e.ip_numbers[0]
2202 ).unwrap_err();
2203
2204 assert!(err.io().is_some());
2205 }
2206
2207 {
2209 use crate::err::ipv6_exts::ExtsWalkError::ExtNotReferenced;
2210
2211 let mut missing_ref = e.clone();
2212 let missing_ext = missing_ref.introduce_missing_ref(post_header);
2213
2214 let mut writer = Vec::with_capacity(e.data.header_len());
2215 let err = missing_ref.data.write(
2216 &mut writer,
2217 missing_ref.ip_numbers[0]
2218 ).unwrap_err();
2219
2220 assert_eq!(
2221 err.content().unwrap(),
2222 &ExtNotReferenced{ missing_ext }
2223 );
2224 }
2225 }
2226 }
2227
2228 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2230
2231 run_test(
2233 &[*first_header, post_header],
2234 &[header_size],
2235 post_header,
2236 );
2237
2238 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2239
2240 run_test(
2242 &[*first_header, *second_header, post_header],
2243 &[header_size],
2244 post_header,
2245 );
2246
2247 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2248 run_test(
2250 &[*first_header, *second_header, *third_header, post_header],
2251 &[header_size],
2252 post_header,
2253 );
2254 }
2255 }
2256 }
2257 }
2258 }
2259
2260 proptest! {
2261 #[test]
2262 fn header_len(
2263 hop_by_hop_options in ipv6_raw_ext_any(),
2264 destination_options in ipv6_raw_ext_any(),
2265 routing in ipv6_raw_ext_any(),
2266 fragment in ipv6_fragment_any(),
2267 auth in ip_auth_any(),
2268 final_destination_options in ipv6_raw_ext_any(),
2269 ) {
2270 {
2272 let exts : Ipv6Extensions = Default::default();
2273 assert_eq!(0, exts.header_len());
2274 }
2275
2276 {
2278 let exts = Ipv6Extensions{
2279 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2280 destination_options: Some(destination_options.clone()),
2281 routing: Some(
2282 Ipv6RoutingExtensions{
2283 routing: routing.clone(),
2284 final_destination_options: Some(final_destination_options.clone()),
2285 }
2286 ),
2287 fragment: Some(fragment.clone()),
2288 auth: Some(auth.clone()),
2289 };
2290 assert_eq!(
2291 exts.header_len(),
2292 (
2293 hop_by_hop_options.header_len() +
2294 destination_options.header_len() +
2295 routing.header_len() +
2296 final_destination_options.header_len() +
2297 fragment.header_len() +
2298 auth.header_len()
2299 )
2300 );
2301 }
2302
2303 {
2305 let exts = Ipv6Extensions{
2306 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2307 destination_options: Some(destination_options.clone()),
2308 routing: Some(
2309 Ipv6RoutingExtensions{
2310 routing: routing.clone(),
2311 final_destination_options: None,
2312 }
2313 ),
2314 fragment: Some(fragment.clone()),
2315 auth: Some(auth.clone()),
2316 };
2317 assert_eq!(
2318 exts.header_len(),
2319 (
2320 hop_by_hop_options.header_len() +
2321 destination_options.header_len() +
2322 routing.header_len() +
2323 fragment.header_len() +
2324 auth.header_len()
2325 )
2326 );
2327 }
2328 }
2329 }
2330
2331 proptest! {
2332 #[test]
2333 fn set_next_headers(
2334 hop_by_hop_options in ipv6_raw_ext_any(),
2335 destination_options in ipv6_raw_ext_any(),
2336 routing in ipv6_raw_ext_any(),
2337 fragment in ipv6_fragment_any(),
2338 auth in ip_auth_any(),
2339 final_destination_options in ipv6_raw_ext_any(),
2340 post_header in ip_number_any()
2341 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2342 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2343 ),
2344 ) {
2345 {
2347 let mut exts : Ipv6Extensions = Default::default();
2348 assert_eq!(post_header, exts.set_next_headers(post_header));
2349 assert!(exts.hop_by_hop_options.is_none());
2350 assert!(exts.destination_options.is_none());
2351 assert!(exts.routing.is_none());
2352 assert!(exts.fragment.is_none());
2353 assert!(exts.auth.is_none());
2354 }
2355
2356 {
2358 let mut exts = Ipv6Extensions{
2359 hop_by_hop_options: Some(hop_by_hop_options.clone()),
2360 destination_options: Some(destination_options.clone()),
2361 routing: Some(
2362 Ipv6RoutingExtensions{
2363 routing: routing.clone(),
2364 final_destination_options: Some(final_destination_options.clone()),
2365 }
2366 ),
2367 fragment: Some(fragment.clone()),
2368 auth: Some(auth.clone()),
2369 };
2370 assert_eq!(IPV6_HOP_BY_HOP, exts.set_next_headers(post_header));
2371
2372 assert_eq!(IPV6_DEST_OPTIONS, exts.hop_by_hop_options.as_ref().unwrap().next_header);
2373 assert_eq!(IPV6_ROUTE, exts.destination_options.as_ref().unwrap().next_header);
2374 assert_eq!(IPV6_FRAG, exts.routing.as_ref().unwrap().routing.next_header);
2375 assert_eq!(AUTH, exts.fragment.as_ref().unwrap().next_header);
2376 assert_eq!(IPV6_DEST_OPTIONS, exts.auth.as_ref().unwrap().next_header);
2377 assert_eq!(post_header, exts.routing.as_ref().unwrap().final_destination_options.as_ref().unwrap().next_header);
2378 }
2379 }
2380 }
2381
2382 proptest! {
2383 #[test]
2384 fn next_header(
2385 header_size in any::<u8>(),
2386 post_header in ip_number_any()
2387 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2388 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2389 ),)
2390 {
2391 {
2393 let exts : Ipv6Extensions = Default::default();
2394 assert_eq!(post_header, exts.next_header(post_header).unwrap());
2395 }
2396
2397 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8], post_header: IpNumber) {
2399 let e = ExtensionTestHeaders::new(
2401 ip_numbers,
2402 header_sizes
2403 );
2404
2405 if e.ip_numbers[1..e.ip_numbers.len()-1].iter().any(|&x| x == IPV6_HOP_BY_HOP) {
2406 use crate::err::ipv6_exts::ExtsWalkError::HopByHopNotAtStart;
2408 assert_eq!(
2409 e.data.next_header(e.ip_numbers[0]).unwrap_err(),
2410 HopByHopNotAtStart
2411 );
2412 } else {
2413 assert_eq!(
2415 *e.ip_numbers.last().unwrap(),
2416 e.data.next_header(e.ip_numbers[0]).unwrap()
2417 );
2418
2419 {
2421 use crate::err::ipv6_exts::ExtsWalkError::ExtNotReferenced;
2422
2423 let mut missing_ref = e.clone();
2424 let missing_ext = missing_ref.introduce_missing_ref(post_header);
2425 assert_eq!(
2426 missing_ref.data.next_header(missing_ref.ip_numbers[0]).unwrap_err(),
2427 ExtNotReferenced{ missing_ext }
2428 );
2429 }
2430 }
2431 }
2432
2433 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
2435
2436 run_test(
2438 &[*first_header, post_header],
2439 &[header_size],
2440 post_header,
2441 );
2442
2443 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
2444
2445 run_test(
2447 &[*first_header, *second_header, post_header],
2448 &[header_size],
2449 post_header,
2450 );
2451
2452 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
2453 run_test(
2455 &[*first_header, *second_header, *third_header, post_header],
2456 &[header_size],
2457 post_header,
2458 );
2459 }
2460 }
2461 }
2462 }
2463 }
2464
2465 #[test]
2466 fn is_fragmenting_payload() {
2467 assert_eq!(
2469 false,
2470 Ipv6Extensions {
2471 hop_by_hop_options: None,
2472 destination_options: None,
2473 routing: None,
2474 fragment: None,
2475 auth: None,
2476 }
2477 .is_fragmenting_payload()
2478 );
2479
2480 assert_eq!(
2482 false,
2483 Ipv6Extensions {
2484 hop_by_hop_options: None,
2485 destination_options: None,
2486 routing: None,
2487 fragment: Some(Ipv6FragmentHeader::new(
2488 ip_number::UDP,
2489 IpFragOffset::ZERO,
2490 false,
2491 0
2492 )),
2493 auth: None,
2494 }
2495 .is_fragmenting_payload()
2496 );
2497
2498 assert!(Ipv6Extensions {
2500 hop_by_hop_options: None,
2501 destination_options: None,
2502 routing: None,
2503 fragment: Some(Ipv6FragmentHeader::new(
2504 ip_number::UDP,
2505 IpFragOffset::ZERO,
2506 true,
2507 0
2508 )),
2509 auth: None,
2510 }
2511 .is_fragmenting_payload());
2512 }
2513
2514 #[test]
2515 fn is_empty() {
2516 assert!(Ipv6Extensions {
2518 hop_by_hop_options: None,
2519 destination_options: None,
2520 routing: None,
2521 fragment: None,
2522 auth: None,
2523 }
2524 .is_empty());
2525
2526 assert_eq!(
2528 false,
2529 Ipv6Extensions {
2530 hop_by_hop_options: Some(
2531 Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6]).unwrap()
2532 ),
2533 destination_options: None,
2534 routing: None,
2535 fragment: None,
2536 auth: None,
2537 }
2538 .is_empty()
2539 );
2540
2541 assert_eq!(
2543 false,
2544 Ipv6Extensions {
2545 hop_by_hop_options: None,
2546 destination_options: Some(
2547 Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6]).unwrap()
2548 ),
2549 routing: None,
2550 fragment: None,
2551 auth: None,
2552 }
2553 .is_empty()
2554 );
2555
2556 assert_eq!(
2558 false,
2559 Ipv6Extensions {
2560 hop_by_hop_options: None,
2561 destination_options: None,
2562 routing: Some(Ipv6RoutingExtensions {
2563 routing: Ipv6RawExtHeader::new_raw(ip_number::UDP, &[1, 2, 3, 4, 5, 6])
2564 .unwrap(),
2565 final_destination_options: None,
2566 }),
2567 fragment: None,
2568 auth: None,
2569 }
2570 .is_empty()
2571 );
2572
2573 assert_eq!(
2575 false,
2576 Ipv6Extensions {
2577 hop_by_hop_options: None,
2578 destination_options: None,
2579 routing: None,
2580 fragment: Some(Ipv6FragmentHeader::new(
2581 ip_number::UDP,
2582 IpFragOffset::ZERO,
2583 true,
2584 0
2585 )),
2586 auth: None,
2587 }
2588 .is_empty()
2589 );
2590
2591 assert_eq!(
2593 false,
2594 Ipv6Extensions {
2595 hop_by_hop_options: None,
2596 destination_options: None,
2597 routing: None,
2598 fragment: None,
2599 auth: Some(IpAuthHeader::new(ip_number::UDP, 0, 0, &[]).unwrap()),
2600 }
2601 .is_empty()
2602 );
2603 }
2604
2605 #[test]
2606 fn debug() {
2607 use alloc::format;
2608
2609 let a: Ipv6Extensions = Default::default();
2610 assert_eq!(
2611 &format!(
2612 "Ipv6Extensions {{ hop_by_hop_options: {:?}, destination_options: {:?}, routing: {:?}, fragment: {:?}, auth: {:?} }}",
2613 a.hop_by_hop_options,
2614 a.destination_options,
2615 a.routing,
2616 a.fragment,
2617 a.auth,
2618 ),
2619 &format!("{:?}", a)
2620 );
2621 }
2622
2623 #[test]
2624 fn clone_eq() {
2625 let a: Ipv6Extensions = Default::default();
2626 assert_eq!(a, a.clone());
2627 }
2628
2629 #[test]
2630 fn default() {
2631 let a: Ipv6Extensions = Default::default();
2632 assert_eq!(a.hop_by_hop_options, None);
2633 assert_eq!(a.destination_options, None);
2634 assert_eq!(a.routing, None);
2635 assert_eq!(a.fragment, None);
2636 assert_eq!(a.auth, None);
2637 }
2638}