Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/net/
lax_net_slice.rs

1use 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)]
18pub 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
27impl<'a> LaxNetSlice<'a> {
28    /// Returns a reference to ip payload if the net slice contains
29    /// an ipv4 or ipv6 slice.
30    #[inline]
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
40impl<'a> From<LaxIpSlice<'a>> for LaxNetSlice<'a> {
41    #[inline]
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
50impl<'a> From<LaxIpv4Slice<'a>> for LaxNetSlice<'a> {
51    #[inline]
52    fn from(value: LaxIpv4Slice<'a>) -> LaxNetSlice<'a> {
53        LaxNetSlice::Ipv4(value)
54    }
55}
56
57impl<'a> From<LaxIpv6Slice<'a>> for LaxNetSlice<'a> {
58    #[inline]
59    fn from(value: LaxIpv6Slice<'a>) -> LaxNetSlice<'a> {
60        LaxNetSlice::Ipv6(value)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use crate::*;
67    use alloc::{format, vec::Vec};
68
69    #[test]
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]
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]
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]
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}