1use super::*;
2use crate::err::LenError;
3use arrayvec::ArrayVec;
4
5#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct PacketHeaders<'a> {
17 pub link: Option<LinkHeader>,
19
20 pub link_exts: ArrayVec<LinkExtHeader, { PacketHeaders::LINK_EXTS_CAP }>,
22
23 pub net: Option<NetHeaders>,
25
26 pub transport: Option<TransportHeader>,
28
29 pub payload: PayloadSlice<'a>,
31}
32
33impl<'a> PacketHeaders<'a> {
34 pub const LINK_EXTS_CAP: usize = 3;
36
37 pub fn from_ethernet_slice(
79 slice: &'a [u8],
80 ) -> Result<PacketHeaders<'a>, err::packet::SliceError> {
81 use err::packet::SliceError::Len;
82
83 let (ethernet, rest) = Ethernet2Header::from_slice(slice).map_err(Len)?;
84 let mut result = Self::from_ether_type(ethernet.ether_type, rest);
85
86 match &mut result {
87 Ok(result) => result.link = Some(LinkHeader::Ethernet2(ethernet)),
89 Err(Len(err)) => err.layer_start_offset += Ethernet2Header::LEN,
91 _ => {}
92 }
93 result
94 }
95
96 pub fn from_ether_type(
150 mut ether_type: EtherType,
151 slice: &'a [u8],
152 ) -> Result<PacketHeaders<'a>, err::packet::SliceError> {
153 use err::packet::SliceError::*;
154
155 let mut rest = slice;
156
157 let add_offset = |mut len_error: LenError, rest: &[u8]| -> LenError {
159 len_error.layer_start_offset += unsafe {
160 rest.as_ptr().offset_from(slice.as_ptr()) as usize
162 };
163 len_error
164 };
165
166 let mut result = PacketHeaders {
167 link: None,
168 link_exts: ArrayVec::new_const(),
169 net: None,
170 transport: None,
171 payload: PayloadSlice::Ether(EtherPayloadSlice {
172 ether_type,
173 len_source: LenSource::Slice,
174 payload: rest,
175 }),
176 };
177
178 use ether_type::*;
179 let mut len_source = LenSource::Slice;
180 loop {
181 match ether_type {
182 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
183 if result.link_exts.is_full() {
184 break;
185 }
186 let (vlan, vlan_rest) = match SingleVlanHeader::from_slice(rest) {
187 Ok(v) => v,
188 Err(err) => {
189 return Err(Len(err.add_offset(slice.len() - rest.len())));
190 }
191 };
192 rest = vlan_rest;
194 ether_type = vlan.ether_type;
195 result.payload = PayloadSlice::Ether(EtherPayloadSlice {
196 ether_type,
197 len_source,
198 payload: rest,
199 });
200 unsafe {
202 result.link_exts.push_unchecked(LinkExtHeader::Vlan(vlan));
203 }
204 }
205 MACSEC => {
206 use err::macsec::HeaderSliceError as I;
207 if result.link_exts.is_full() {
208 break;
209 }
210 let macsec = match MacsecSlice::from_slice(rest) {
211 Ok(v) => v,
212 Err(I::Len(err)) => {
213 return Err(Len(err.add_offset(slice.len() - rest.len())));
214 }
215 Err(I::Content(err)) => {
216 return Err(Macsec(err));
217 }
218 };
219
220 unsafe {
222 result
223 .link_exts
224 .push_unchecked(LinkExtHeader::Macsec(macsec.header.to_header()));
225 }
226
227 use MacsecPayloadSlice::*;
228 match macsec.payload {
229 Unmodified(e) => {
230 rest = e.payload;
231 ether_type = e.ether_type;
232 if e.len_source != LenSource::Slice {
233 len_source = e.len_source;
234 }
235 result.payload = PayloadSlice::Ether(EtherPayloadSlice {
236 ether_type: e.ether_type,
237 len_source,
238 payload: e.payload,
239 });
240 }
241 Modified(m) => {
242 result.payload = PayloadSlice::MacsecMod(m);
243 return Ok(result);
244 }
245 }
246 }
247 _ => {
248 break;
249 }
250 }
251 }
252
253 match ether_type {
255 IPV4 => {
256 let (ip, ip_payload) = IpHeaders::from_ipv4_slice(rest).map_err(|err| {
258 use err::ipv4::SliceError as I;
259 match err {
260 I::Len(err) => Len(add_offset(err, rest)),
261 I::Header(err) => Ipv4(err),
262 I::Exts(err) => Ipv4Exts(err),
263 }
264 })?;
265
266 rest = ip_payload.payload;
268 result.net = Some(ip.into());
269 result.payload = PayloadSlice::Ip(ip_payload.clone());
270
271 let (transport, payload) = read_transport(ip_payload).map_err(|err| {
273 use err::tcp::HeaderSliceError as I;
274 match err {
275 I::Len(err) => Len(add_offset(err, rest)),
276 I::Content(err) => Tcp(err),
277 }
278 })?;
279
280 result.transport = transport;
281 result.payload = payload;
282 }
283 IPV6 => {
284 let (ip, ip_payload) = IpHeaders::from_ipv6_slice(rest).map_err(|err| {
286 use err::ipv6::SliceError as I;
287 match err {
288 I::Len(err) => Len(add_offset(err, rest)),
289 I::Header(err) => Ipv6(err),
290 I::Exts(err) => Ipv6Exts(err),
291 }
292 })?;
293
294 rest = ip_payload.payload;
296 result.net = Some(ip.into());
297 result.payload = PayloadSlice::Ip(ip_payload.clone());
298
299 let (transport, payload) = read_transport(ip_payload).map_err(|err| {
301 use err::tcp::HeaderSliceError as I;
302 match err {
303 I::Len(err) => Len(add_offset(err, rest)),
304 I::Content(err) => Tcp(err),
305 }
306 })?;
307
308 result.transport = transport;
309 result.payload = payload;
310 }
311 ARP => {
312 result.net = Some(NetHeaders::Arp(
313 ArpPacket::from_slice(rest).map_err(|err| Len(add_offset(err, rest)))?,
314 ));
315
316 result.payload = PayloadSlice::Empty;
317 }
318 _ => {}
319 };
320
321 Ok(result)
322 }
323
324 pub fn from_ip_slice(slice: &[u8]) -> Result<PacketHeaders, err::packet::SliceError> {
364 use err::packet::SliceError::*;
365
366 let (ip_header, ip_payload) = IpHeaders::from_slice(slice).map_err(|err| {
368 use err::ip::HeadersSliceError as I;
369 match err {
370 I::Len(err) => Len(err),
371 I::Content(err) => match err {
372 err::ip::HeadersError::Ip(err) => Ip(err),
373 err::ip::HeadersError::Ipv4Ext(err) => Ipv4Exts(err),
374 err::ip::HeadersError::Ipv6Ext(err) => Ipv6Exts(err),
375 },
376 }
377 })?;
378
379 let mut result = PacketHeaders {
380 link: None,
381 link_exts: ArrayVec::new_const(),
382 net: Some(ip_header.into()),
383 transport: None,
384 payload: PayloadSlice::Ip(ip_payload.clone()),
385 };
386
387 let rest = ip_payload.payload;
389
390 let (transport, payload) = read_transport(ip_payload).map_err(|err| {
392 use err::tcp::HeaderSliceError as I;
393 match err {
394 I::Len(mut err) => {
395 err.layer_start_offset += unsafe {
396 rest.as_ptr().offset_from(slice.as_ptr()) as usize
398 };
399 Len(err)
400 }
401 I::Content(err) => Tcp(err),
402 }
403 })?;
404
405 result.transport = transport;
407 result.payload = payload;
408
409 Ok(result)
410 }
411
412 pub fn vlan(&self) -> Option<VlanHeader> {
414 let mut result = None;
415 for ext in &self.link_exts {
416 if let LinkExtHeader::Vlan(s) = ext {
417 if let Some(outer) = result {
418 return Some(VlanHeader::Double(DoubleVlanHeader {
419 outer,
420 inner: s.clone(),
421 }));
422 } else {
423 result = Some(s.clone());
424 }
425 }
426 }
427 result.map(VlanHeader::Single)
428 }
429
430 pub fn vlan_ids(&self) -> ArrayVec<VlanId, { PacketHeaders::LINK_EXTS_CAP }> {
432 let mut result = ArrayVec::<VlanId, { PacketHeaders::LINK_EXTS_CAP }>::new_const();
433 for e in &self.link_exts {
434 if let LinkExtHeader::Vlan(s) = e {
435 unsafe {
437 result.push_unchecked(s.vlan_id);
438 }
439 }
440 }
441 result
442 }
443}
444
445fn read_transport(
447 ip_payload: IpPayloadSlice,
448) -> Result<(Option<TransportHeader>, PayloadSlice), err::tcp::HeaderSliceError> {
449 if ip_payload.fragmented {
450 Ok((None, PayloadSlice::Ip(ip_payload)))
451 } else {
452 let add_len_source = |mut len_error: LenError| -> err::tcp::HeaderSliceError {
454 if LenSource::Slice == len_error.len_source {
456 len_error.len_source = ip_payload.len_source;
457 }
458 Len(len_error)
459 };
460 use crate::ip_number::*;
461 use err::tcp::HeaderSliceError::*;
462 match ip_payload.ip_number {
463 ICMP => Icmpv4Slice::from_slice(ip_payload.payload)
464 .map_err(add_len_source)
465 .map(|value| {
466 (
467 Some(TransportHeader::Icmpv4(value.header())),
468 PayloadSlice::Icmpv4(value.payload()),
469 )
470 }),
471 IPV6_ICMP => Icmpv6Slice::from_slice(ip_payload.payload)
472 .map_err(add_len_source)
473 .map(|value| {
474 (
475 Some(TransportHeader::Icmpv6(value.header())),
476 PayloadSlice::Icmpv6(value.payload()),
477 )
478 }),
479 UDP => UdpHeader::from_slice(ip_payload.payload)
480 .map_err(add_len_source)
481 .map(|value| {
482 (
483 Some(TransportHeader::Udp(value.0)),
484 PayloadSlice::Udp(value.1),
485 )
486 }),
487 TCP => TcpHeader::from_slice(ip_payload.payload)
488 .map_err(|err| match err {
489 Len(err) => add_len_source(err),
490 Content(err) => Content(err),
491 })
492 .map(|value| {
493 (
494 Some(TransportHeader::Tcp(value.0)),
495 PayloadSlice::Tcp(value.1),
496 )
497 }),
498 _ => Ok((None, PayloadSlice::Ip(ip_payload))),
499 }
500 }
501}
502
503#[cfg(test)]
504mod test {
505 use super::*;
506 use crate::err::packet::SliceError;
507 use crate::err::Layer;
508 use crate::test_packet::TestPacket;
509
510 const VLAN_ETHER_TYPES: [EtherType; 3] = [
511 ether_type::VLAN_TAGGED_FRAME,
512 ether_type::PROVIDER_BRIDGING,
513 ether_type::VLAN_DOUBLE_TAGGED_FRAME,
514 ];
515 const MACSEC_ETHER_TYPES: [EtherType; 1] = [ether_type::MACSEC];
516
517 #[test]
518 fn debug() {
519 use alloc::format;
520 let header = PacketHeaders {
521 link: None,
522 link_exts: ArrayVec::new_const(),
523 net: None,
524 transport: None,
525 payload: PayloadSlice::Ether(EtherPayloadSlice {
526 ether_type: EtherType(0),
527 len_source: LenSource::Slice,
528 payload: &[],
529 }),
530 };
531 assert_eq!(
532 &format!("{:?}", header),
533 &format!(
534 "PacketHeaders {{ link: {:?}, link_exts: {:?}, net: {:?}, transport: {:?}, payload: {:?} }}",
535 header.link,
536 header.link_exts,
537 header.net,
538 header.transport,
539 header.payload
540 )
541 );
542 }
543
544 #[test]
545 fn clone_eq() {
546 let header = PacketHeaders {
547 link: None,
548 link_exts: ArrayVec::new_const(),
549 net: None,
550 transport: None,
551 payload: PayloadSlice::Ether(EtherPayloadSlice {
552 ether_type: EtherType(0),
553 len_source: LenSource::Slice,
554 payload: &[],
555 }),
556 };
557 assert_eq!(header.clone(), header);
558 }
559
560 #[test]
561 fn vlan_vlan_ids() {
562 {
564 let headers = PacketHeaders {
565 link: None,
566 link_exts: ArrayVec::new_const(),
567 net: None,
568 transport: None,
569 payload: PayloadSlice::Empty,
570 };
571 assert_eq!(headers.vlan(), None);
572 assert_eq!(headers.vlan_ids(), ArrayVec::<VlanId, 3>::new_const());
573 }
574
575 {
577 let outer = SingleVlanHeader {
578 pcp: VlanPcp::ZERO,
579 drop_eligible_indicator: false,
580 vlan_id: VlanId::try_new(1).unwrap(),
581 ether_type: EtherType::WAKE_ON_LAN,
582 };
583 let headers = PacketHeaders {
584 link: None,
585 link_exts: {
586 let mut exts = ArrayVec::new_const();
587 exts.push(LinkExtHeader::Vlan(outer.clone()));
588 exts
589 },
590 net: None,
591 transport: None,
592 payload: PayloadSlice::Empty,
593 };
594
595 assert_eq!(headers.vlan(), Some(VlanHeader::Single(outer.clone())));
596 assert_eq!(headers.vlan_ids(), {
597 let mut ids = ArrayVec::<VlanId, 3>::new_const();
598 ids.push(VlanId::try_new(1).unwrap());
599 ids
600 });
601 }
602
603 {
605 let outer = SingleVlanHeader {
606 pcp: VlanPcp::ZERO,
607 drop_eligible_indicator: false,
608 vlan_id: VlanId::try_new(1).unwrap(),
609 ether_type: EtherType::VLAN_TAGGED_FRAME,
610 };
611 let inner = SingleVlanHeader {
612 pcp: VlanPcp::ZERO,
613 drop_eligible_indicator: false,
614 vlan_id: VlanId::try_new(2).unwrap(),
615 ether_type: EtherType::WAKE_ON_LAN,
616 };
617 let headers = PacketHeaders {
618 link: None,
619 link_exts: {
620 let mut exts = ArrayVec::new_const();
621 exts.push(LinkExtHeader::Vlan(outer.clone()));
622 exts.push(LinkExtHeader::Vlan(inner.clone()));
623 exts
624 },
625 net: None,
626 transport: None,
627 payload: PayloadSlice::Empty,
628 };
629
630 assert_eq!(
631 headers.vlan(),
632 Some(VlanHeader::Double(DoubleVlanHeader {
633 outer: outer.clone(),
634 inner: inner.clone(),
635 }))
636 );
637 assert_eq!(headers.vlan_ids(), {
638 let mut ids = ArrayVec::<VlanId, 3>::new_const();
639 ids.push(VlanId::try_new(1).unwrap());
640 ids.push(VlanId::try_new(2).unwrap());
641 ids
642 });
643 }
644
645 {
647 let vlan1 = SingleVlanHeader {
648 pcp: VlanPcp::ZERO,
649 drop_eligible_indicator: false,
650 vlan_id: VlanId::try_new(1).unwrap(),
651 ether_type: EtherType::VLAN_TAGGED_FRAME,
652 };
653 let vlan2 = SingleVlanHeader {
654 pcp: VlanPcp::ZERO,
655 drop_eligible_indicator: false,
656 vlan_id: VlanId::try_new(2).unwrap(),
657 ether_type: EtherType::WAKE_ON_LAN,
658 };
659 let vlan3 = SingleVlanHeader {
660 pcp: VlanPcp::ZERO,
661 drop_eligible_indicator: false,
662 vlan_id: VlanId::try_new(3).unwrap(),
663 ether_type: EtherType::WAKE_ON_LAN,
664 };
665 let headers = PacketHeaders {
666 link: None,
667 link_exts: {
668 let mut exts = ArrayVec::new_const();
669 exts.push(LinkExtHeader::Vlan(vlan1.clone()));
670 exts.push(LinkExtHeader::Vlan(vlan2.clone()));
671 exts.push(LinkExtHeader::Vlan(vlan3.clone()));
672 exts
673 },
674 net: None,
675 transport: None,
676 payload: PayloadSlice::Empty,
677 };
678
679 assert_eq!(
680 headers.vlan(),
681 Some(VlanHeader::Double(DoubleVlanHeader {
682 outer: vlan1.clone(),
683 inner: vlan2.clone(),
684 }))
685 );
686 assert_eq!(headers.vlan_ids(), {
687 let mut ids = ArrayVec::<VlanId, 3>::new_const();
688 ids.push(VlanId::try_new(1).unwrap());
689 ids.push(VlanId::try_new(2).unwrap());
690 ids.push(VlanId::try_new(3).unwrap());
691 ids
692 });
693 }
694 }
695
696 #[test]
697 fn from_x_slice() {
698 from_x_slice_link_exts_variants(&TestPacket {
700 link: None,
701 link_exts: ArrayVec::new_const(),
702 net: None,
703 transport: None,
704 });
705
706 {
708 let eth = Ethernet2Header {
709 source: [1, 2, 3, 4, 5, 6],
710 destination: [1, 2, 3, 4, 5, 6],
711 ether_type: 0.into(),
712 };
713 let test = TestPacket {
714 link: Some(LinkHeader::Ethernet2(eth.clone())),
715 link_exts: ArrayVec::new_const(),
716 net: None,
717 transport: None,
718 };
719
720 from_x_slice_link_exts_variants(&test);
722
723 {
725 let data = test.to_vec(&[]);
726 for len in 0..data.len() {
727 let err = LenError {
728 required_len: eth.header_len(),
729 len,
730 len_source: LenSource::Slice,
731 layer: err::Layer::Ethernet2Header,
732 layer_start_offset: 0,
733 };
734
735 from_slice_assert_err(&test, &data[..len], SliceError::Len(err.clone()));
736 }
737 }
738 }
739 }
740
741 fn from_x_slice_link_exts_variants(base: &TestPacket) {
742 #[derive(Copy, Clone, Eq, PartialEq)]
743 enum Ext {
744 Macsec,
745 VlanTaggedFrame,
746 VlanDoubleTaggedFrame,
747 ProviderBridging,
748 }
749
750 impl Ext {
751 pub fn ether_type(&self) -> EtherType {
752 match self {
753 Ext::Macsec => EtherType::MACSEC,
754 Ext::VlanTaggedFrame => EtherType::VLAN_TAGGED_FRAME,
755 Ext::VlanDoubleTaggedFrame => EtherType::VLAN_DOUBLE_TAGGED_FRAME,
756 Ext::ProviderBridging => EtherType::PROVIDER_BRIDGING,
757 }
758 }
759
760 pub fn add(&self, base: &TestPacket) -> TestPacket {
761 let mut test = base.clone();
762 test.set_ether_type(self.ether_type());
763 test.link_exts
764 .try_push(match self {
765 Ext::Macsec => LinkExtHeader::Macsec(MacsecHeader {
766 ptype: MacsecPType::Unmodified(EtherType(3)),
767 endstation_id: false,
768 scb: false,
769 an: MacsecAn::ZERO,
770 short_len: MacsecShortLen::ZERO,
771 packet_nr: 0,
772 sci: None,
773 }),
774 Ext::VlanTaggedFrame
775 | Ext::VlanDoubleTaggedFrame
776 | Ext::ProviderBridging => LinkExtHeader::Vlan(SingleVlanHeader {
777 pcp: VlanPcp::ZERO,
778 drop_eligible_indicator: false,
779 vlan_id: VlanId::try_new(1).unwrap(),
780 ether_type: 3.into(),
781 }),
782 })
783 .unwrap();
784 test
785 }
786 }
787
788 let test_macsec_mod = |test: &TestPacket| {
789 for ptype in [
790 MacsecPType::Modified,
791 MacsecPType::Encrypted,
792 MacsecPType::EncryptedUnmodified,
793 ] {
794 let mut test = test.clone();
795 if let Some(LinkExtHeader::Macsec(m)) = test.link_exts.last_mut() {
796 m.ptype = ptype;
797 }
798 if matches!(test.link_exts.last(), Some(LinkExtHeader::Macsec(_))) {
799 from_x_slice_assert_ok(&test);
800 }
801 }
802 };
803
804 let len_errors = |test: &TestPacket| {
805 let data = test.to_vec(&[]);
806 let req_len = test.link_exts.last().unwrap().header_len();
807 for len in 0..req_len {
808 let base_len = test.len(&[]) - req_len;
809
810 let (err_req_len, err_layer) = match test.link_exts.last().unwrap() {
811 LinkExtHeader::Vlan(h) => (h.header_len(), Layer::VlanHeader),
812 LinkExtHeader::Macsec(_) => {
813 if len < 6 {
814 (6, Layer::MacsecHeader)
815 } else {
816 (req_len, Layer::MacsecHeader)
817 }
818 }
819 };
820
821 let mut len_source = LenSource::Slice;
822 for prev_exts in test.link_exts.iter().rev().skip(1) {
823 if let LinkExtHeader::Macsec(m) = prev_exts {
824 if m.short_len != MacsecShortLen::ZERO {
825 len_source = LenSource::MacsecShortLength;
826 }
827 }
828 }
829
830 let err = LenError {
831 required_len: err_req_len,
832 len,
833 len_source,
834 layer: err_layer,
835 layer_start_offset: base_len,
836 };
837 from_slice_assert_err(&test, &data[..base_len + len], SliceError::Len(err.clone()));
838 }
839 };
840
841 let content_errors = |test: &TestPacket| {
842 if let Some(LinkExtHeader::Macsec(last)) = test.link_exts.last() {
843 let mut data = test.to_vec(&[]);
844
845 let macsec_offset = data.len() - last.header_len();
847 data[macsec_offset] = data[macsec_offset] | 0b1000_0000;
848
849 from_slice_assert_err(
850 &test,
851 &data,
852 SliceError::Macsec(err::macsec::HeaderError::UnexpectedVersion),
853 );
854 }
855 };
856
857 let extensions = [
859 Ext::Macsec,
860 Ext::VlanTaggedFrame,
861 Ext::VlanDoubleTaggedFrame,
862 Ext::ProviderBridging,
863 ];
864
865 from_x_slice_net_variants(base);
867
868 for ext0 in extensions {
870 let test0 = ext0.add(base);
871 from_x_slice_net_variants(&test0);
872 test_macsec_mod(&test0);
873 len_errors(&test0);
874 content_errors(&test0);
875
876 for ext1 in extensions {
877 let test1 = ext1.add(&test0);
878 from_x_slice_net_variants(&test1);
879 test_macsec_mod(&test1);
880 len_errors(&test1);
881 content_errors(&test1);
882
883 for ext2 in extensions {
884 let test2 = ext2.add(&test1);
885 from_x_slice_net_variants(&test2);
886 test_macsec_mod(&test2);
887 len_errors(&test2);
888 content_errors(&test2);
889
890 for ext3 in extensions {
892 let mut test3 = test2.clone();
893 let l = test3.link_exts.last_mut().unwrap();
894 match l {
895 LinkExtHeader::Vlan(s) => {
896 s.ether_type = ext3.ether_type();
897 }
898 LinkExtHeader::Macsec(m) => {
899 m.ptype = MacsecPType::Unmodified(ext3.ether_type());
900 }
901 }
902 from_x_slice_assert_ok(&test3);
903 }
904 }
905 }
906 }
907 }
908
909 fn from_x_slice_net_variants(base: &TestPacket) {
910 from_x_slice_transport_variants(base);
912
913 for fragmented in [false, true] {
915 let ipv4 = {
916 let mut ipv4 =
917 Ipv4Header::new(0, 1, 2.into(), [3, 4, 5, 6], [7, 8, 9, 10]).unwrap();
918 ipv4.more_fragments = fragmented;
919 ipv4
920 };
921
922 {
923 let mut test = base.clone();
924 test.set_ether_type(ether_type::IPV4);
925 test.net = Some(NetHeaders::Ipv4(ipv4.clone(), Default::default()));
926
927 from_x_slice_transport_variants(&test);
929
930 {
932 let data = test.to_vec(&[]);
933 for len in 0..ipv4.header_len() {
934 let base_len = test.len(&[]) - ipv4.header_len();
935
936 let err = LenError {
937 required_len: ipv4.header_len(),
938 len,
939 len_source: LenSource::Slice,
940 layer: err::Layer::Ipv4Header,
941 layer_start_offset: base_len,
942 };
943 from_slice_assert_err(
944 &test,
945 &data[..base_len + len],
946 if test.link.is_some() || !test.link_exts.is_empty() {
947 SliceError::Len(err.clone())
948 } else {
949 SliceError::Len({
950 if len < 1 {
951 let mut err = err.clone();
952 err.required_len = 1;
953 err.layer = err::Layer::IpHeader;
954 err
955 } else {
956 err.clone()
957 }
958 })
959 },
960 );
961 }
962 }
963
964 {
966 let mut data = test.to_vec(&[]);
967 let ipv4_offset = data.len() - ipv4.header_len();
968
969 data[ipv4_offset] = 0b1111_0000 & data[ipv4_offset];
971
972 from_slice_assert_err(
973 &test,
974 &data,
975 if test.link.is_some() || !test.link_exts.is_empty() {
976 SliceError::Ipv4(
977 err::ipv4::HeaderError::HeaderLengthSmallerThanHeader { ihl: 0 },
978 )
979 } else {
980 SliceError::Ip(
981 err::ip::HeaderError::Ipv4HeaderLengthSmallerThanHeader { ihl: 0 },
982 )
983 },
984 );
985 }
986 }
987
988 {
990 let auth = IpAuthHeader::new(0.into(), 1, 2, &[]).unwrap();
991
992 let mut test = base.clone();
993 test.set_ether_type(ether_type::IPV4);
994 test.net = Some(NetHeaders::Ipv4(
995 {
996 let mut ipv4 = ipv4.clone();
997 ipv4.protocol = ip_number::AUTH;
998 ipv4
999 },
1000 Ipv4Extensions {
1001 auth: Some(auth.clone()),
1002 },
1003 ));
1004 test.set_payload_len(0);
1005
1006 from_x_slice_transport_variants(&test);
1008
1009 for len in 0..auth.header_len() {
1011 let mut test = test.clone();
1013 test.set_payload_len_ip(-1 * (auth.header_len() as isize) + (len as isize));
1014 test.set_payload_len_link_ext(
1015 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len
1016 - auth.header_len(),
1017 );
1018
1019 let data = test.to_vec(&[]);
1020 let base_len = test.len(&[]) - auth.header_len();
1021
1022 let err = LenError {
1023 required_len: auth.header_len(),
1024 len,
1025 len_source: LenSource::Ipv4HeaderTotalLen,
1026 layer: err::Layer::IpAuthHeader,
1027 layer_start_offset: base_len,
1028 };
1029
1030 from_slice_assert_err(
1031 &test,
1032 &data[..base_len + len],
1033 SliceError::Len(err.clone()),
1034 );
1035 }
1036
1037 {
1039 let mut data = test.to_vec(&[]);
1040 let auth_offset = data.len() - auth.header_len();
1041
1042 data[auth_offset + 1] = 0;
1044
1045 let err = err::ip_auth::HeaderError::ZeroPayloadLen;
1047 from_slice_assert_err(&test, &data, SliceError::Ipv4Exts(err.clone()));
1048 }
1049 }
1050 }
1051
1052 {
1054 let ipv6 = Ipv6Header {
1055 traffic_class: 0,
1056 flow_label: 1.try_into().unwrap(),
1057 payload_length: 2,
1058 next_header: 3.into(),
1059 hop_limit: 4,
1060 source: [0; 16],
1061 destination: [0; 16],
1062 };
1063
1064 {
1066 let mut test = base.clone();
1067 test.set_ether_type(ether_type::IPV6);
1068 test.net = Some(NetHeaders::Ipv6(ipv6.clone(), Default::default()));
1069 test.set_payload_len(0);
1070
1071 from_x_slice_transport_variants(&test);
1073
1074 for len in 0..ipv6.header_len() {
1076 let mut test = test.clone();
1077 test.set_payload_len_link_ext(len);
1078
1079 let base_len = test.len(&[]) - ipv6.header_len();
1080 let data = test.to_vec(&[]);
1081 let err = err::LenError {
1082 required_len: ipv6.header_len(),
1083 len,
1084 len_source: LenSource::Slice,
1085 layer: err::Layer::Ipv6Header,
1086 layer_start_offset: base_len,
1087 };
1088
1089 from_slice_assert_err(
1090 &test,
1091 &data[..base_len + len],
1092 if test.link.is_some() || !test.link_exts.is_empty() {
1093 SliceError::Len(err.clone())
1094 } else {
1095 SliceError::Len({
1096 if len < 1 {
1097 let mut err = err.clone();
1098 err.required_len = 1;
1099 err.layer = err::Layer::IpHeader;
1100 err
1101 } else {
1102 err.clone()
1103 }
1104 })
1105 },
1106 );
1107 }
1108
1109 {
1111 use err::ip::HeaderError::*;
1112 let mut data = test.to_vec(&[]);
1113
1114 let base_len = data.len() - ipv6.header_len();
1116 data[base_len] = data[base_len] & 0b0000_1111;
1117
1118 from_slice_assert_err(
1119 &test,
1120 &data,
1121 if test.link.is_some() || !test.link_exts.is_empty() {
1122 SliceError::Ipv6(err::ipv6::HeaderError::UnexpectedVersion {
1123 version_number: 0,
1124 })
1125 } else {
1126 SliceError::Ip(UnsupportedIpVersion { version_number: 0 })
1127 },
1128 );
1129 }
1130 }
1131
1132 for fragment in [false, true] {
1134 let auth = IpAuthHeader::new(ip_number::GGP, 1, 2, &[]).unwrap();
1135 let frag = Ipv6FragmentHeader {
1136 next_header: ip_number::AUTH,
1137 fragment_offset: 0.try_into().unwrap(),
1138 more_fragments: fragment,
1139 identification: 3,
1140 };
1141
1142 let mut test = base.clone();
1143 test.set_ether_type(ether_type::IPV6);
1144 test.net = Some(NetHeaders::Ipv6(
1145 {
1146 let mut ipv6 = ipv6.clone();
1147 ipv6.next_header = ip_number::IPV6_FRAG;
1148 ipv6
1149 },
1150 {
1151 let mut exts: Ipv6Extensions = Default::default();
1152 exts.fragment = Some(frag.clone());
1153 exts.auth = Some(auth.clone());
1154 exts
1155 },
1156 ));
1157 test.set_payload_len(0);
1158
1159 from_x_slice_transport_variants(&test);
1161
1162 for len in 0..auth.header_len() {
1164 let mut test = test.clone();
1166 test.set_payload_len_ip(-1 * (auth.header_len() as isize) + (len as isize));
1167 test.set_payload_len_link_ext(
1168 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len
1169 - auth.header_len(),
1170 );
1171
1172 let data = test.to_vec(&[]);
1173 let base_len = test.len(&[]) - auth.header_len();
1174
1175 let err = LenError {
1176 required_len: auth.header_len(),
1177 len,
1178 len_source: LenSource::Ipv6HeaderPayloadLen,
1179 layer: err::Layer::IpAuthHeader,
1180 layer_start_offset: base_len,
1181 };
1182 from_slice_assert_err(
1183 &test,
1184 &data[..base_len + len],
1185 SliceError::Len(err.clone()),
1186 );
1187 }
1188
1189 {
1191 let mut data = test.to_vec(&[]);
1192 let auth_offset = data.len() - auth.header_len();
1193 data[auth_offset + 1] = 0;
1195
1196 let err = err::ip_auth::HeaderError::ZeroPayloadLen;
1197 from_slice_assert_err(
1198 &test,
1199 &data,
1200 SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::IpAuth(err.clone())),
1201 );
1202 }
1203
1204 {
1206 let mut data = test.to_vec(&[]);
1207 let auth_offset = data.len() - auth.header_len();
1208
1209 data[auth_offset] = 0;
1211
1212 from_slice_assert_err(
1213 &test,
1214 &data,
1215 SliceError::Ipv6Exts(err::ipv6_exts::HeaderError::HopByHopNotAtStart),
1216 );
1217 }
1218 }
1219 }
1220
1221 {
1223 let arp = ArpPacket::new(
1224 ArpHardwareId::ETHERNET,
1225 EtherType::IPV4,
1226 ArpOperation::REPLY,
1227 &[0u8; 6],
1228 &[0u8; 4],
1229 &[0u8; 6],
1230 &[0u8; 4],
1231 )
1232 .unwrap();
1233
1234 let mut test = base.clone();
1235 test.set_ether_type(ether_type::ARP);
1236 test.net = Some(NetHeaders::Arp(arp.clone()));
1237 test.set_payload_len(0);
1238
1239 from_x_slice_assert_ok(&test);
1241
1242 {
1244 for len in 0..arp.packet_len() {
1245 let mut test = test.clone();
1246 test.set_payload_len_link_ext(len);
1247 let base_len = test.len(&[]) - arp.packet_len();
1248 let data = test.to_vec(&[]);
1249
1250 let err = err::LenError {
1251 required_len: if len < 8 { 8 } else { arp.packet_len() },
1252 len,
1253 len_source: if len < 8 {
1254 LenSource::Slice
1255 } else {
1256 LenSource::ArpAddrLengths
1257 },
1258 layer: Layer::Arp,
1259 layer_start_offset: base_len,
1260 };
1261
1262 from_slice_assert_err(
1263 &test,
1264 &data[..base_len + len],
1265 SliceError::Len({
1266 if len < 8 {
1267 let mut err = err.clone();
1268 err.required_len = 8;
1269 err.layer = Layer::Arp;
1270 err
1271 } else {
1272 err.clone()
1273 }
1274 }),
1275 );
1276 }
1277 }
1278 }
1279 }
1280
1281 fn from_x_slice_transport_variants(base: &TestPacket) {
1282 from_x_slice_assert_ok(base);
1284
1285 if let Some(ip) = &base.net {
1287 {
1289 let udp = UdpHeader {
1290 source_port: 1,
1291 destination_port: 2,
1292 length: 3,
1293 checksum: 4,
1294 };
1295 let mut test = base.clone();
1296 test.net = Some({
1297 let mut ip = match ip {
1298 NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1299 NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1300 NetHeaders::Arp(_) => unreachable!(),
1301 };
1302 ip.set_next_headers(ip_number::UDP);
1303 ip.into()
1304 });
1305 test.transport = Some(TransportHeader::Udp(udp.clone()));
1306 test.set_payload_len(0);
1307
1308 from_x_slice_assert_ok(&test);
1310
1311 if false == test.is_ip_payload_fragmented() {
1313 for len in 0..udp.header_len() {
1314 let mut test = test.clone();
1316
1317 test.set_payload_len_ip(len as isize);
1319 test.set_payload_len_link_ext(
1320 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len,
1321 );
1322
1323 let data = test.to_vec(&[]);
1325 let base_len = test.len(&[]) - udp.header_len();
1326
1327 let err = LenError {
1328 required_len: udp.header_len(),
1329 len,
1330 len_source: match test.net.as_ref().unwrap() {
1331 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1332 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1333 NetHeaders::Arp(_) => unreachable!(),
1334 },
1335 layer: err::Layer::UdpHeader,
1336 layer_start_offset: base_len,
1337 };
1338 from_slice_assert_err(
1339 &test,
1340 &data[..base_len + len],
1341 SliceError::Len(err.clone()),
1342 );
1343 }
1344 }
1345 }
1346
1347 {
1349 let tcp = TcpHeader::new(1, 2, 3, 4);
1350 let mut test = base.clone();
1351 test.net = Some({
1352 let mut ip = match ip {
1353 NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1354 NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1355 NetHeaders::Arp(_) => unreachable!(),
1356 };
1357 ip.set_next_headers(ip_number::TCP);
1358 ip.into()
1359 });
1360 test.transport = Some(TransportHeader::Tcp(tcp.clone()));
1361 test.set_payload_len(0);
1362
1363 from_x_slice_assert_ok(&test);
1365
1366 if false == test.is_ip_payload_fragmented() {
1368 for len in 0..(tcp.header_len() as usize) {
1370 let mut test = test.clone();
1372 test.set_payload_len_ip(len as isize);
1373 test.set_payload_len_link_ext(
1374 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len,
1375 );
1376
1377 let data = test.to_vec(&[]);
1378 let base_len = test.len(&[]) - (tcp.header_len() as usize);
1379
1380 let err = LenError {
1381 required_len: tcp.header_len() as usize,
1382 len,
1383 len_source: match test.net.as_ref().unwrap() {
1384 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1385 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1386 NetHeaders::Arp(_) => unreachable!(),
1387 },
1388 layer: err::Layer::TcpHeader,
1389 layer_start_offset: base_len,
1390 };
1391 from_slice_assert_err(
1392 &test,
1393 &data[..base_len + len],
1394 SliceError::Len(err.clone()),
1395 );
1396 }
1397
1398 {
1400 let mut data = test.to_vec(&[]);
1401 let base_len = test.len(&[]) - (tcp.header_len() as usize);
1402
1403 data[base_len + 12] = data[base_len + 12] & 0b0000_1111;
1405
1406 let err = err::tcp::HeaderError::DataOffsetTooSmall { data_offset: 0 };
1407 from_slice_assert_err(&test, &data, SliceError::Tcp(err.clone()));
1408 }
1409 }
1410 }
1411
1412 {
1414 let icmpv4 =
1415 Icmpv4Header::new(Icmpv4Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1416 let mut test = base.clone();
1417 test.net = Some({
1418 let mut ip = match ip {
1419 NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1420 NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1421 NetHeaders::Arp(_) => unreachable!(),
1422 };
1423 ip.set_next_headers(ip_number::ICMP);
1424 ip.into()
1425 });
1426 test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
1427
1428 from_x_slice_assert_ok(&test);
1430
1431 if false == test.is_ip_payload_fragmented() {
1433 for len in 0..icmpv4.header_len() {
1434 let mut test = test.clone();
1436 test.set_payload_len_ip(len as isize);
1437 test.set_payload_len_link_ext(
1438 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len,
1439 );
1440
1441 let data = test.to_vec(&[]);
1442 let base_len = test.len(&[]) - icmpv4.header_len();
1443
1444 let err = LenError {
1445 required_len: icmpv4.header_len(),
1446 len,
1447 len_source: match test.net.as_ref().unwrap() {
1448 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1449 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1450 NetHeaders::Arp(_) => unreachable!(),
1451 },
1452 layer: err::Layer::Icmpv4,
1453 layer_start_offset: base_len,
1454 };
1455 from_slice_assert_err(
1456 &test,
1457 &data[..base_len + len],
1458 SliceError::Len(err.clone()),
1459 );
1460 }
1461 }
1462 }
1463
1464 {
1466 let icmpv6 =
1467 Icmpv6Header::new(Icmpv6Type::EchoReply(IcmpEchoHeader { id: 1, seq: 2 }));
1468 let mut test = base.clone();
1469 test.net = Some({
1470 let mut ip = match ip {
1471 NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
1472 NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
1473 NetHeaders::Arp(_) => unreachable!(),
1474 };
1475 ip.set_next_headers(ip_number::IPV6_ICMP);
1476 ip.into()
1477 });
1478 test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
1479
1480 from_x_slice_assert_ok(&test);
1482
1483 if false == test.is_ip_payload_fragmented() {
1485 for len in 0..icmpv6.header_len() {
1486 let mut test = test.clone();
1488 test.set_payload_len_ip(len as isize);
1489 test.set_payload_len_link_ext(
1490 test.net.as_ref().map(|v| v.header_len()).unwrap_or(0) + len,
1491 );
1492
1493 let data = test.to_vec(&[]);
1494 let base_len = test.len(&[]) - icmpv6.header_len();
1495
1496 let err = LenError {
1497 required_len: icmpv6.header_len(),
1498 len,
1499 len_source: match test.net.as_ref().unwrap() {
1500 NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
1501 NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
1502 NetHeaders::Arp(_) => unreachable!(),
1503 },
1504 layer: err::Layer::Icmpv6,
1505 layer_start_offset: base_len,
1506 };
1507 from_slice_assert_err(
1508 &test,
1509 &data[..base_len + len],
1510 SliceError::Len(err.clone()),
1511 );
1512 }
1513 }
1514 }
1515 }
1516 }
1517
1518 fn from_x_slice_assert_ok(test_base: &TestPacket) {
1519 let payload = [1, 2, 3, 4];
1520
1521 let test = {
1523 let mut test = test_base.clone();
1524 test.set_payload_len(payload.len());
1525 test
1526 };
1527
1528 let is_fragmented = test.is_ip_payload_fragmented();
1530
1531 let data = test.to_vec(&payload);
1533
1534 if test.link.is_some() {
1536 let result = PacketHeaders::from_ethernet_slice(&data).unwrap();
1537 assert_eq!(result.link, test.link);
1538 assert_eq!(result.link_exts, test.link_exts);
1539 assert_eq!(result.net, test.net);
1540 if is_fragmented {
1541 assert_eq!(result.transport, None);
1542 } else {
1543 assert_eq!(result.transport, test.transport);
1544 if test.has_arp() {
1545 assert_eq!(result.payload.slice(), &[]);
1546 } else {
1547 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1548 }
1549 }
1550 }
1551 if test.link.is_none() && !test.link_exts.is_empty() {
1553 let ether_types: &[EtherType] = match test.link_exts.first().unwrap() {
1554 LinkExtHeader::Vlan(_) => &VLAN_ETHER_TYPES,
1555 LinkExtHeader::Macsec(_) => &MACSEC_ETHER_TYPES,
1556 };
1557 for ether_type in ether_types {
1558 let result = PacketHeaders::from_ether_type(*ether_type, &data).unwrap();
1559 assert_eq!(result.link, test.link);
1560 assert_eq!(result.link_exts, test.link_exts);
1561 assert_eq!(result.net, test.net);
1562 if is_fragmented {
1563 assert_eq!(result.transport, None);
1564 } else {
1565 assert_eq!(result.transport, test.transport);
1566 if test.has_arp() {
1567 assert_eq!(result.payload.slice(), &[]);
1568 } else {
1569 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1570 }
1571 }
1572 }
1573 }
1574 if test.link.is_none() && test.link_exts.is_empty() {
1576 if let Some(ip) = &test.net {
1577 let result = PacketHeaders::from_ether_type(
1578 match ip {
1579 NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1580 NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1581 NetHeaders::Arp(_) => ether_type::ARP,
1582 },
1583 &data,
1584 )
1585 .unwrap();
1586 assert_eq!(result.link, test.link);
1587 assert_eq!(result.link_exts, test.link_exts);
1588 assert_eq!(result.net, test.net);
1589 if is_fragmented {
1590 assert_eq!(result.transport, None);
1591 } else {
1592 assert_eq!(result.transport, test.transport);
1593 if test.has_arp() {
1594 assert_eq!(result.payload.slice(), &[]);
1595 } else {
1596 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1597 }
1598 }
1599 }
1600 }
1601 if test.link.is_none()
1603 && test.link_exts.is_empty()
1604 && test.net.as_ref().map(|v| v.is_ip()).unwrap_or(false)
1605 {
1606 let result = PacketHeaders::from_ip_slice(&data).unwrap();
1607 assert_eq!(result.link, test.link);
1608 assert_eq!(result.link_exts, test.link_exts);
1609 assert_eq!(result.net, test.net);
1610 if is_fragmented {
1611 assert_eq!(result.transport, None);
1612 } else {
1613 assert_eq!(result.transport, test.transport);
1614 assert_eq!(result.payload.slice(), &[1, 2, 3, 4]);
1615 }
1616 }
1617 }
1618
1619 fn from_slice_assert_err(test: &TestPacket, data: &[u8], err: SliceError) {
1622 if test.link.is_some() {
1624 assert_eq!(
1625 err.clone(),
1626 PacketHeaders::from_ethernet_slice(&data).unwrap_err()
1627 );
1628 }
1629 if test.link.is_none() && !test.link_exts.is_empty() {
1631 let ether_types: &[EtherType] = match test.link_exts.first().unwrap() {
1632 LinkExtHeader::Vlan(_) => &VLAN_ETHER_TYPES,
1633 LinkExtHeader::Macsec(_) => &MACSEC_ETHER_TYPES,
1634 };
1635 for ether_type in ether_types {
1636 assert_eq!(
1637 err.clone(),
1638 PacketHeaders::from_ether_type(*ether_type, &data).unwrap_err()
1639 );
1640 }
1641 }
1642 if test.link.is_none() && test.link_exts.is_empty() {
1644 if let Some(ip) = &test.net {
1645 let err = PacketHeaders::from_ether_type(
1646 match ip {
1647 NetHeaders::Ipv4(_, _) => ether_type::IPV4,
1648 NetHeaders::Ipv6(_, _) => ether_type::IPV6,
1649 NetHeaders::Arp(_) => ether_type::ARP,
1650 },
1651 &data,
1652 )
1653 .unwrap_err();
1654 assert_eq!(err, err.clone());
1655 }
1656 }
1657 if test.link.is_none()
1659 && test.link_exts.is_empty()
1660 && test.net.as_ref().map(|v| v.is_ip()).unwrap_or(false)
1661 {
1662 assert_eq!(err, PacketHeaders::from_ip_slice(&data).unwrap_err());
1663 }
1664 }
1665}