• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::*;
2 
3 /// Slice containing laxly parsed the network headers & payloads (e.g. IPv4, IPv6, ARP).
4 ///
5 /// Compared to the normal [`NetSlice`] this slice allows the
6 /// payload to be incomplete/cut off and errors to be present in
7 /// the IpPayload.
8 ///
9 /// The main usecases for "laxly" parsed slices are are:
10 ///
11 /// * Parsing packets that have been cut off. This is, for example, useful to
12 ///   parse packets returned via ICMP as these usually only contain the start.
13 /// * Parsing packets where the `total_len` (for IPv4) or `payload_len` (for IPv6)
14 ///   have not yet been set. This can be useful when parsing packets which have
15 ///   been recorded in a layer before the length field was set (e.g. before the
16 ///   operating system set the length fields).
17 #[derive(Clone, Debug, Eq, PartialEq)]
18 pub enum LaxNetSlice<'a> {
19     /// IPv4 header & the decoded extension headers.
20     Ipv4(LaxIpv4Slice<'a>),
21     /// IPv6 header & the decoded extension headers.
22     Ipv6(LaxIpv6Slice<'a>),
23     /// "Address Resolution Protocol" Packet,
24     Arp(ArpPacketSlice<'a>),
25 }
26 
27 impl<'a> LaxNetSlice<'a> {
28     /// Returns a reference to ip payload if the net slice contains
29     /// an ipv4 or ipv6 slice.
30     #[inline]
ip_payload_ref(&self) -> Option<&LaxIpPayloadSlice<'a>>31     pub fn ip_payload_ref(&self) -> Option<&LaxIpPayloadSlice<'a>> {
32         match self {
33             LaxNetSlice::Ipv4(s) => Some(&s.payload),
34             LaxNetSlice::Ipv6(s) => Some(&s.payload),
35             LaxNetSlice::Arp(_) => None,
36         }
37     }
38 }
39 
40 impl<'a> From<LaxIpSlice<'a>> for LaxNetSlice<'a> {
41     #[inline]
from(value: LaxIpSlice<'a>) -> LaxNetSlice<'a>42     fn from(value: LaxIpSlice<'a>) -> LaxNetSlice<'a> {
43         match value {
44             LaxIpSlice::Ipv4(ipv4) => LaxNetSlice::Ipv4(ipv4),
45             LaxIpSlice::Ipv6(ipv6) => LaxNetSlice::Ipv6(ipv6),
46         }
47     }
48 }
49 
50 impl<'a> From<LaxIpv4Slice<'a>> for LaxNetSlice<'a> {
51     #[inline]
from(value: LaxIpv4Slice<'a>) -> LaxNetSlice<'a>52     fn from(value: LaxIpv4Slice<'a>) -> LaxNetSlice<'a> {
53         LaxNetSlice::Ipv4(value)
54     }
55 }
56 
57 impl<'a> From<LaxIpv6Slice<'a>> for LaxNetSlice<'a> {
58     #[inline]
from(value: LaxIpv6Slice<'a>) -> LaxNetSlice<'a>59     fn from(value: LaxIpv6Slice<'a>) -> LaxNetSlice<'a> {
60         LaxNetSlice::Ipv6(value)
61     }
62 }
63 
64 #[cfg(test)]
65 mod tests {
66     use crate::*;
67     use alloc::{format, vec::Vec};
68 
69     #[test]
debug()70     fn debug() {
71         let bytes = Ipv6Header {
72             next_header: IpNumber::UDP,
73             ..Default::default()
74         }
75         .to_bytes();
76         let s = LaxIpv6Slice::from_slice(&bytes).unwrap().0;
77         let n = LaxNetSlice::Ipv6(s.clone());
78         assert_eq!(format!("{n:?}"), format!("Ipv6({s:?})"));
79     }
80 
81     #[test]
clone_eq()82     fn clone_eq() {
83         let bytes = Ipv6Header {
84             next_header: IpNumber::UDP,
85             ..Default::default()
86         }
87         .to_bytes();
88         let s = LaxNetSlice::Ipv6(LaxIpv6Slice::from_slice(&bytes).unwrap().0);
89         assert_eq!(s, s.clone())
90     }
91 
92     #[test]
ip_payload_ref()93     fn ip_payload_ref() {
94         // ipv4
95         {
96             let payload = [1, 2, 3, 4];
97             let bytes = {
98                 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
99                 bytes.extend_from_slice(
100                     &(Ipv4Header {
101                         total_len: Ipv4Header::MIN_LEN_U16 + 4,
102                         protocol: IpNumber::UDP,
103                         ..Default::default()
104                     })
105                     .to_bytes(),
106                 );
107                 bytes.extend_from_slice(&payload);
108                 bytes
109             };
110             let s = LaxNetSlice::Ipv4(LaxIpv4Slice::from_slice(&bytes).unwrap().0);
111             assert_eq!(
112                 s.ip_payload_ref(),
113                 Some(&LaxIpPayloadSlice {
114                     ip_number: IpNumber::UDP,
115                     fragmented: false,
116                     len_source: LenSource::Ipv4HeaderTotalLen,
117                     payload: &payload,
118                     incomplete: false,
119                 })
120             );
121         }
122         // ipv6
123         {
124             let payload = [1, 2, 3, 4];
125             let bytes = {
126                 let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
127                 bytes.extend_from_slice(
128                     &(Ipv6Header {
129                         next_header: IpNumber::UDP,
130                         payload_length: 4,
131                         ..Default::default()
132                     })
133                     .to_bytes(),
134                 );
135                 bytes.extend_from_slice(&payload);
136                 bytes
137             };
138             let s = LaxNetSlice::Ipv6(LaxIpv6Slice::from_slice(&bytes).unwrap().0);
139             assert_eq!(
140                 s.ip_payload_ref(),
141                 Some(&LaxIpPayloadSlice {
142                     ip_number: IpNumber::UDP,
143                     fragmented: false,
144                     len_source: LenSource::Ipv6HeaderPayloadLen,
145                     payload: &payload,
146                     incomplete: false,
147                 })
148             );
149         }
150     }
151 
152     #[test]
from()153     fn from() {
154         // IpSlice::Ipv4
155         {
156             let payload = [1, 2, 3, 4];
157             let bytes = {
158                 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
159                 bytes.extend_from_slice(
160                     &(Ipv4Header {
161                         total_len: Ipv4Header::MIN_LEN_U16 + 4,
162                         protocol: IpNumber::UDP,
163                         ..Default::default()
164                     })
165                     .to_bytes(),
166                 );
167                 bytes.extend_from_slice(&payload);
168                 bytes
169             };
170             let i = LaxIpv4Slice::from_slice(&bytes).unwrap().0;
171             let actual: LaxNetSlice = LaxIpSlice::Ipv4(i.clone()).into();
172             assert_eq!(LaxNetSlice::Ipv4(i.clone()), actual);
173         }
174         // LaxIpv4Slice
175         {
176             let payload = [1, 2, 3, 4];
177             let bytes = {
178                 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
179                 bytes.extend_from_slice(
180                     &(Ipv4Header {
181                         total_len: Ipv4Header::MIN_LEN_U16 + 4,
182                         protocol: IpNumber::UDP,
183                         ..Default::default()
184                     })
185                     .to_bytes(),
186                 );
187                 bytes.extend_from_slice(&payload);
188                 bytes
189             };
190             let i = LaxIpv4Slice::from_slice(&bytes).unwrap().0;
191             let actual: LaxNetSlice = i.clone().into();
192             assert_eq!(LaxNetSlice::Ipv4(i.clone()), actual);
193         }
194         // IpSlice::Ipv6
195         {
196             let payload = [1, 2, 3, 4];
197             let bytes = {
198                 let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
199                 bytes.extend_from_slice(
200                     &(Ipv6Header {
201                         next_header: IpNumber::UDP,
202                         payload_length: 4,
203                         ..Default::default()
204                     })
205                     .to_bytes(),
206                 );
207                 bytes.extend_from_slice(&payload);
208                 bytes
209             };
210             let i = LaxIpv6Slice::from_slice(&bytes).unwrap().0;
211             let actual: LaxNetSlice = i.clone().into();
212             assert_eq!(LaxNetSlice::Ipv6(i.clone()), actual);
213         }
214     }
215 }
216