1use crate::err::{ipv6::SliceError, Layer, LenError};
2use crate::*;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct Ipv6Slice<'a> {
7 pub(crate) header: Ipv6HeaderSlice<'a>,
8 pub(crate) exts: Ipv6ExtensionsSlice<'a>,
9 pub(crate) payload: IpPayloadSlice<'a>,
10}
11
12impl<'a> Ipv6Slice<'a> {
13 pub fn from_slice(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError> {
24 let header = Ipv6HeaderSlice::from_slice(slice).map_err(|err| {
26 use crate::err::ipv6::HeaderSliceError::*;
27 match err {
28 Len(err) => SliceError::Len(err),
29 Content(err) => SliceError::Header(err),
30 }
31 })?;
32
33 let (header_payload, len_source) =
35 if 0 == header.payload_length() && slice.len() > Ipv6Header::LEN {
36 (
42 unsafe {
43 core::slice::from_raw_parts(
44 slice.as_ptr().add(Ipv6Header::LEN),
45 slice.len() - Ipv6Header::LEN,
46 )
47 },
48 LenSource::Slice,
49 )
50 } else {
51 let payload_len = usize::from(header.payload_length());
52 let expected_len = Ipv6Header::LEN + payload_len;
53 if slice.len() < expected_len {
54 return Err(SliceError::Len(LenError {
55 required_len: expected_len,
56 len: slice.len(),
57 len_source: LenSource::Slice,
58 layer: Layer::Ipv6Packet,
59 layer_start_offset: 0,
60 }));
61 } else {
62 (
63 unsafe {
64 core::slice::from_raw_parts(
65 slice.as_ptr().add(Ipv6Header::LEN),
66 payload_len,
67 )
68 },
69 LenSource::Ipv6HeaderPayloadLen,
70 )
71 }
72 };
73
74 let (exts, payload_ip_number, payload) =
76 Ipv6ExtensionsSlice::from_slice(header.next_header(), header_payload).map_err(
77 |err| {
78 use crate::err::ipv6_exts::HeaderSliceError::*;
80 match err {
81 Len(mut err) => {
82 err.len_source = LenSource::Ipv6HeaderPayloadLen;
83 err.layer_start_offset += Ipv6Header::LEN;
84 SliceError::Len(err)
85 }
86 Content(err) => SliceError::Exts(err),
87 }
88 },
89 )?;
90
91 let fragmented = exts.is_fragmenting_payload();
92 Ok(Ipv6Slice {
93 header,
94 exts,
95 payload: IpPayloadSlice {
96 ip_number: payload_ip_number,
97 fragmented,
98 len_source,
99 payload,
100 },
101 })
102 }
103
104 pub fn from_slice_lax(slice: &'a [u8]) -> Result<Ipv6Slice<'a>, SliceError> {
140 let header = Ipv6HeaderSlice::from_slice(slice).map_err(|err| {
142 use crate::err::ipv6::HeaderSliceError::*;
143 match err {
144 Len(err) => SliceError::Len(err),
145 Content(err) => SliceError::Header(err),
146 }
147 })?;
148
149 let (header_payload, len_source) =
151 if 0 == header.payload_length() && slice.len() > Ipv6Header::LEN {
152 (
158 unsafe {
159 core::slice::from_raw_parts(
160 slice.as_ptr().add(Ipv6Header::LEN),
161 slice.len() - Ipv6Header::LEN,
162 )
163 },
164 LenSource::Slice,
165 )
166 } else {
167 let payload_len = usize::from(header.payload_length());
168 let expected_len = Ipv6Header::LEN + payload_len;
169 if slice.len() < expected_len {
170 (
171 unsafe {
172 core::slice::from_raw_parts(
173 slice.as_ptr().add(Ipv6Header::LEN),
174 slice.len() - Ipv6Header::LEN,
175 )
176 },
177 LenSource::Slice,
178 )
179 } else {
180 (
181 unsafe {
182 core::slice::from_raw_parts(
183 slice.as_ptr().add(Ipv6Header::LEN),
184 payload_len,
185 )
186 },
187 LenSource::Ipv6HeaderPayloadLen,
188 )
189 }
190 };
191
192 let (exts, payload_ip_number, payload) =
194 Ipv6ExtensionsSlice::from_slice(header.next_header(), header_payload).map_err(
195 |err| {
196 use crate::err::ipv6_exts::HeaderSliceError::*;
198 match err {
199 Len(mut err) => {
200 err.len_source = len_source;
201 err.layer_start_offset += Ipv6Header::LEN;
202 SliceError::Len(err)
203 }
204 Content(err) => SliceError::Exts(err),
205 }
206 },
207 )?;
208
209 let fragmented = exts.is_fragmenting_payload();
210 Ok(Ipv6Slice {
211 header,
212 exts,
213 payload: IpPayloadSlice {
214 ip_number: payload_ip_number,
215 fragmented,
216 len_source,
217 payload,
218 },
219 })
220 }
221
222 #[inline]
224 pub fn header(&self) -> Ipv6HeaderSlice<'a> {
225 self.header
226 }
227
228 #[inline]
230 pub fn extensions(&self) -> &Ipv6ExtensionsSlice<'a> {
231 &self.exts
232 }
233
234 #[inline]
237 pub fn payload(&self) -> &IpPayloadSlice<'a> {
238 &self.payload
239 }
240
241 #[inline]
243 pub fn is_payload_fragmented(&self) -> bool {
244 self.payload.fragmented
245 }
246}
247
248#[cfg(test)]
249mod test {
250 use super::*;
251 use crate::{
252 ip_number::{AUTH, IGMP, UDP},
253 test_gens::*,
254 };
255 use alloc::{format, vec::Vec};
256 use proptest::prelude::*;
257
258 proptest! {
259 #[test]
260 fn debug_clone_eq(
261 ipv6_base in ipv6_any(),
262 auth_base in ip_auth_any()
263 ) {
264 let mut auth = auth_base.clone();
265 auth.next_header = IGMP;
266 let payload: [u8;4] = [1,2,3,4];
267 let mut data = Vec::with_capacity(
268 ipv6_base.header_len() +
269 auth.header_len() +
270 payload.len()
271 );
272 let mut ipv6 = ipv6_base.clone();
273 ipv6.next_header = AUTH;
274 ipv6.payload_length = (auth.header_len() + payload.len()) as u16;
275 data.extend_from_slice(&ipv6.to_bytes());
276 data.extend_from_slice(&auth.to_bytes());
277 data.extend_from_slice(&payload);
278
279 let slice = Ipv6Slice::from_slice(&data).unwrap();
281
282 prop_assert_eq!(
284 format!("{:?}", slice),
285 format!(
286 "Ipv6Slice {{ header: {:?}, exts: {:?}, payload: {:?} }}",
287 slice.header(),
288 slice.extensions(),
289 slice.payload()
290 )
291 );
292 prop_assert_eq!(slice.clone(), slice);
293 }
294 }
295
296 proptest! {
297 #[test]
298 fn from_slice(
299 ipv6_base in ipv6_any(),
300 auth_base in ip_auth_any()
301 ) {
302 let payload: [u8;6] = [1,2,3,4,5,6];
303
304 let data_without_ext = {
306 let mut data = Vec::with_capacity(
307 ipv6_base.header_len() +
308 payload.len() +
309 4
310 );
311 let mut ipv6 = ipv6_base.clone();
312 ipv6.payload_length = (payload.len()) as u16;
313 ipv6.next_header = UDP;
314 data.extend_from_slice(&ipv6.to_bytes());
315 data.extend_from_slice(&payload);
316 data.extend_from_slice(&[0,0,0,0]);
317 data
318 };
319 let data_with_ext = {
320 let payload: [u8;6] = [1,2,3,4,5,6];
321 let mut data = Vec::with_capacity(
322 ipv6_base.header_len() +
323 auth_base.header_len() +
324 payload.len() +
325 4
326 );
327 let mut ipv6 = ipv6_base.clone();
328 ipv6.payload_length = (auth_base.header_len() + payload.len()) as u16;
329 ipv6.next_header = AUTH;
330 let mut auth = auth_base.clone();
331 auth.next_header = UDP;
332 data.extend_from_slice(&ipv6.to_bytes());
333 data.extend_from_slice(&auth.to_bytes());
334 data.extend_from_slice(&payload);
335 data.extend_from_slice(&[0,0,0,0]);
336 data
337 };
338
339 {
341 let actual = Ipv6Slice::from_slice(&data_without_ext).unwrap();
342 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]);
343 prop_assert!(actual.extensions().first_header().is_none());
344 prop_assert_eq!(
345 actual.payload(),
346 &IpPayloadSlice{
347 ip_number: UDP.into(),
348 fragmented: false,
349 len_source: LenSource::Ipv6HeaderPayloadLen,
350 payload: &payload,
351 }
352 );
353 }
354
355 {
357 let actual = Ipv6Slice::from_slice(&data_with_ext).unwrap();
358 prop_assert_eq!(actual.header().slice(), &data_with_ext[..ipv6_base.header_len()]);
359 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data_with_ext[ipv6_base.header_len()..]).unwrap();
360 prop_assert_eq!(
361 actual.extensions(),
362 &expected
363 );
364 prop_assert_eq!(
365 actual.payload(),
366 &IpPayloadSlice{
367 ip_number: UDP.into(),
368 fragmented: false,
369 len_source: LenSource::Ipv6HeaderPayloadLen,
370 payload: &payload,
371 }
372 );
373 }
374
375 {
377 let mut data = data_without_ext.clone();
379 data[4] = 0;
380 data[5] = 0;
381 let actual = Ipv6Slice::from_slice(&data).unwrap();
382 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]);
383 prop_assert!(actual.extensions().first_header().is_none());
384 prop_assert_eq!(
385 actual.payload(),
386 &IpPayloadSlice{
387 ip_number: UDP.into(),
388 fragmented: false,
389 len_source: LenSource::Slice,
390 payload: &data[ipv6_base.header_len()..],
391 }
392 );
393 }
394
395 {
397 let mut data = data_with_ext.clone();
399 data[4] = 0;
400 data[5] = 0;
401 let actual = Ipv6Slice::from_slice(&data).unwrap();
402 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]);
403 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data[ipv6_base.header_len()..]).unwrap();
404 prop_assert_eq!(
405 actual.extensions(),
406 &expected
407 );
408 prop_assert_eq!(
409 actual.payload(),
410 &IpPayloadSlice{
411 ip_number: UDP.into(),
412 fragmented: false,
413 len_source: LenSource::Slice,
414 payload: &data[ipv6_base.header_len() + auth_base.header_len()..],
415 }
416 );
417 }
418
419 {
421 use crate::err::ipv6::HeaderError;
422 let mut data = data_without_ext.clone();
424 data[0] = data[0] & 0x0f; prop_assert_eq!(
426 Ipv6Slice::from_slice(&data).unwrap_err(),
427 SliceError::Header(
428 HeaderError::UnexpectedVersion{ version_number: 0 }
429 )
430 );
431 }
432
433 for len in 0..Ipv6Header::LEN {
435 prop_assert_eq!(
436 Ipv6Slice::from_slice(&data_without_ext[..len]).unwrap_err(),
437 SliceError::Len(
438 LenError{
439 required_len: Ipv6Header::LEN,
440 len,
441 len_source: LenSource::Slice,
442 layer: Layer::Ipv6Header,
443 layer_start_offset: 0
444 }
445 )
446 );
447 }
448
449 {
451 use crate::err::{LenError, Layer};
452
453 let required_len = ipv6_base.header_len() + payload.len();
454 prop_assert_eq!(
455 Ipv6Slice::from_slice(&data_without_ext[..required_len - 1]).unwrap_err(),
456 SliceError::Len(LenError{
457 required_len: required_len,
458 len: required_len - 1,
459 len_source: LenSource::Slice,
460 layer: Layer::Ipv6Packet,
461 layer_start_offset: 0,
462 })
463 );
464 }
465
466 {
468 use crate::err::{LenError, Layer};
469
470 let required_len = ipv6_base.header_len() + auth_base.header_len() + payload.len();
471 prop_assert_eq!(
472 Ipv6Slice::from_slice(&data_with_ext[..required_len - 1]).unwrap_err(),
473 SliceError::Len(LenError{
474 required_len: required_len,
475 len: required_len - 1,
476 len_source: LenSource::Slice,
477 layer: Layer::Ipv6Packet,
478 layer_start_offset: 0,
479 })
480 );
481 }
482
483 {
485 use crate::err::{LenError, Layer};
486
487 let mut data = data_with_ext.clone();
489 let payload_len_too_small = auth_base.header_len() - 1;
490 {
491 let plts = (payload_len_too_small as u16).to_be_bytes();
492 data[4] = plts[0];
493 data[5] = plts[1];
494 }
495
496 prop_assert_eq!(
497 Ipv6Slice::from_slice(&data).unwrap_err(),
498 SliceError::Len(
499 LenError{
500 required_len: auth_base.header_len(),
501 len: auth_base.header_len() - 1,
502 len_source: LenSource::Ipv6HeaderPayloadLen,
503 layer: Layer::IpAuthHeader,
504 layer_start_offset: ipv6_base.header_len(),
505 }
506 )
507 );
508 }
509
510 {
512 use crate::err::{ip_auth, ipv6_exts};
513
514 let mut data = data_with_ext.clone();
516 data[ipv6_base.header_len() + 1] = 0;
517
518 prop_assert_eq!(
519 Ipv6Slice::from_slice(&data).unwrap_err(),
520 SliceError::Exts(ipv6_exts::HeaderError::IpAuth(
521 ip_auth::HeaderError::ZeroPayloadLen
522 ))
523 );
524 }
525 }
526 }
527
528 proptest! {
529 #[test]
530 fn from_slice_lax(
531 ipv6_base in ipv6_any(),
532 auth_base in ip_auth_any()
533 ) {
534 let payload: [u8;6] = [1,2,3,4,5,6];
535
536 let data_without_ext = {
538 let mut data = Vec::with_capacity(
539 ipv6_base.header_len() +
540 payload.len() +
541 4
542 );
543 let mut ipv6 = ipv6_base.clone();
544 ipv6.payload_length = (payload.len()) as u16;
545 ipv6.next_header = UDP;
546 data.extend_from_slice(&ipv6.to_bytes());
547 data.extend_from_slice(&payload);
548 data.extend_from_slice(&[0,0,0,0]);
549 data
550 };
551 let data_with_ext = {
552 let payload: [u8;6] = [1,2,3,4,5,6];
553 let mut data = Vec::with_capacity(
554 ipv6_base.header_len() +
555 auth_base.header_len() +
556 payload.len() +
557 4
558 );
559 let mut ipv6 = ipv6_base.clone();
560 ipv6.payload_length = (auth_base.header_len() + payload.len()) as u16;
561 ipv6.next_header = AUTH;
562 let mut auth = auth_base.clone();
563 auth.next_header = UDP;
564 data.extend_from_slice(&ipv6.to_bytes());
565 data.extend_from_slice(&auth.to_bytes());
566 data.extend_from_slice(&payload);
567 data.extend_from_slice(&[0,0,0,0]);
568 data
569 };
570
571 {
573 let actual = Ipv6Slice::from_slice_lax(&data_without_ext).unwrap();
574 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]);
575 prop_assert!(actual.extensions().first_header().is_none());
576 prop_assert_eq!(
577 actual.payload(),
578 &IpPayloadSlice{
579 ip_number: UDP.into(),
580 fragmented: false,
581 len_source: LenSource::Ipv6HeaderPayloadLen,
582 payload: &payload,
583 }
584 );
585 }
586
587 {
589 let actual = Ipv6Slice::from_slice_lax(&data_with_ext).unwrap();
590 prop_assert_eq!(actual.header().slice(), &data_with_ext[..ipv6_base.header_len()]);
591 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data_with_ext[ipv6_base.header_len()..]).unwrap();
592 prop_assert_eq!(
593 actual.extensions(),
594 &expected
595 );
596 prop_assert_eq!(
597 actual.payload(),
598 &IpPayloadSlice{
599 ip_number: UDP.into(),
600 fragmented: false,
601 len_source: LenSource::Ipv6HeaderPayloadLen,
602 payload: &payload,
603 }
604 );
605 }
606
607 {
609 let mut data = data_without_ext.clone();
611 data[4] = 0;
612 data[5] = 0;
613 let actual = Ipv6Slice::from_slice_lax(&data).unwrap();
614 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]);
615 prop_assert!(actual.extensions().first_header().is_none());
616 prop_assert_eq!(
617 actual.payload(),
618 &IpPayloadSlice{
619 ip_number: UDP.into(),
620 fragmented: false,
621 len_source: LenSource::Slice,
622 payload: &data[ipv6_base.header_len()..],
623 }
624 );
625 }
626
627 {
629 let mut data = data_with_ext.clone();
631 data[4] = 0;
632 data[5] = 0;
633 let actual = Ipv6Slice::from_slice_lax(&data).unwrap();
634 prop_assert_eq!(actual.header().slice(), &data[..ipv6_base.header_len()]);
635 let (expected, _, _) = Ipv6ExtensionsSlice::from_slice(AUTH, &data[ipv6_base.header_len()..]).unwrap();
636 prop_assert_eq!(
637 actual.extensions(),
638 &expected
639 );
640 prop_assert_eq!(
641 actual.payload(),
642 &IpPayloadSlice{
643 ip_number: UDP.into(),
644 fragmented: false,
645 len_source: LenSource::Slice,
646 payload: &data[ipv6_base.header_len() + auth_base.header_len()..],
647 }
648 );
649 }
650
651 {
653 use crate::err::ipv6::HeaderError;
654 let mut data = data_without_ext.clone();
656 data[0] = data[0] & 0x0f; prop_assert_eq!(
658 Ipv6Slice::from_slice_lax(&data).unwrap_err(),
659 SliceError::Header(
660 HeaderError::UnexpectedVersion{ version_number: 0 }
661 )
662 );
663 }
664
665 for len in 0..Ipv6Header::LEN {
667 prop_assert_eq!(
668 Ipv6Slice::from_slice_lax(&data_without_ext[..len]).unwrap_err(),
669 SliceError::Len(
670 LenError{
671 required_len: Ipv6Header::LEN,
672 len,
673 len_source: LenSource::Slice,
674 layer: Layer::Ipv6Header,
675 layer_start_offset: 0
676 }
677 )
678 );
679 }
680
681 {
683 let len = ipv6_base.header_len() + payload.len() - 1;
684 let actual = Ipv6Slice::from_slice_lax(&data_without_ext[..len]).unwrap();
685 prop_assert_eq!(actual.header().slice(), &data_without_ext[..ipv6_base.header_len()]);
686 prop_assert_eq!(
687 0,
688 actual.extensions().slice().len()
689 );
690 prop_assert_eq!(
691 actual.payload(),
692 &IpPayloadSlice{
693 ip_number: UDP.into(),
694 fragmented: false,
695 len_source: LenSource::Slice,
696 payload: &data_without_ext[ipv6_base.header_len()..len],
697 }
698 );
699 }
700
701 {
703 use crate::err::{LenError, Layer};
704
705 let required_len = ipv6_base.header_len() + auth_base.header_len();
706 prop_assert_eq!(
707 Ipv6Slice::from_slice_lax(&data_with_ext[..required_len - 1]).unwrap_err(),
708 SliceError::Len(LenError{
709 required_len: required_len - Ipv6Header::LEN,
710 len: required_len - Ipv6Header::LEN - 1,
711 len_source: LenSource::Slice,
712 layer: Layer::IpAuthHeader,
713 layer_start_offset: Ipv6Header::LEN,
714 })
715 );
716 }
717
718 {
720 use crate::err::{LenError, Layer};
721
722 let mut data = data_with_ext.clone();
724 let payload_len_too_small = auth_base.header_len() - 1;
725 {
726 let plts = (payload_len_too_small as u16).to_be_bytes();
727 data[4] = plts[0];
728 data[5] = plts[1];
729 }
730
731 prop_assert_eq!(
732 Ipv6Slice::from_slice_lax(&data).unwrap_err(),
733 SliceError::Len(
734 LenError{
735 required_len: auth_base.header_len(),
736 len: auth_base.header_len() - 1,
737 len_source: LenSource::Ipv6HeaderPayloadLen,
738 layer: Layer::IpAuthHeader,
739 layer_start_offset: ipv6_base.header_len(),
740 }
741 )
742 );
743 }
744
745 {
747 use crate::err::{ip_auth, ipv6_exts};
748
749 let mut data = data_with_ext.clone();
751 data[ipv6_base.header_len() + 1] = 0;
752
753 prop_assert_eq!(
754 Ipv6Slice::from_slice_lax(&data).unwrap_err(),
755 SliceError::Exts(ipv6_exts::HeaderError::IpAuth(
756 ip_auth::HeaderError::ZeroPayloadLen
757 ))
758 );
759 }
760 }
761 }
762
763 #[test]
764 fn is_payload_fragmented() {
765 use crate::ip_number::{IPV6_FRAG, UDP};
766
767 {
769 let data = Ipv6Header {
770 traffic_class: 0,
771 flow_label: 1.try_into().unwrap(),
772 payload_length: 0,
773 next_header: UDP,
774 hop_limit: 4,
775 source: [0; 16],
776 destination: [0; 16],
777 }
778 .to_bytes();
779 assert_eq!(
780 false,
781 Ipv6Slice::from_slice(&data)
782 .unwrap()
783 .is_payload_fragmented()
784 );
785 }
786
787 {
789 let ipv6_frag = Ipv6FragmentHeader {
790 next_header: UDP,
791 fragment_offset: 0.try_into().unwrap(),
792 more_fragments: true,
793 identification: 0,
794 };
795 let ipv6 = Ipv6Header {
796 traffic_class: 0,
797 flow_label: 1.try_into().unwrap(),
798 payload_length: ipv6_frag.header_len() as u16,
799 next_header: IPV6_FRAG,
800 hop_limit: 4,
801 source: [0; 16],
802 destination: [0; 16],
803 };
804
805 let mut data = Vec::with_capacity(ipv6.header_len() + ipv6_frag.header_len());
806 data.extend_from_slice(&ipv6.to_bytes());
807 data.extend_from_slice(&ipv6_frag.to_bytes());
808 assert!(Ipv6Slice::from_slice(&data)
809 .unwrap()
810 .is_payload_fragmented());
811 }
812 }
813}