etherparse/net/
net_slice.rs

1use crate::*;
2
3/// Deprecated use [`crate::NetSlice`] or [`crate::IpSlice`] instead.
4#[cfg(feature = "std")]
5#[deprecated(
6    since = "0.14.0",
7    note = "Deprecated use crate::NetSlice or crate::IpSlice instead"
8)]
9pub use NetSlice as InternetSlice;
10
11/// Slice containing the network headers & payloads (e.g. IPv4, IPv6, ARP).
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub enum NetSlice<'a> {
14    /// The ipv4 header & the decoded extension headers.
15    Ipv4(Ipv4Slice<'a>),
16    /// The ipv6 header & the decoded extension headers.
17    Ipv6(Ipv6Slice<'a>),
18    /// The arp header & the decoded extension headers.
19    Arp(ArpPacketSlice<'a>),
20}
21
22impl<'a> NetSlice<'a> {
23    /// Returns true if the NetSlice contains either IPv4 or IPv6.
24    #[inline]
25    pub fn is_ip(&self) -> bool {
26        use NetSlice::*;
27        matches!(self, Ipv4(_) | Ipv6(_))
28    }
29
30    /// Returns true if the NetSlice contains IPv4.
31    #[inline]
32    pub fn is_ipv4(&self) -> bool {
33        use NetSlice::*;
34        matches!(self, Ipv4(_))
35    }
36
37    /// Returns true if the NetSlice contains IPv6.
38    #[inline]
39    pub fn is_ipv6(&self) -> bool {
40        use NetSlice::*;
41        matches!(self, Ipv6(_))
42    }
43
44    /// Returns true if the NetSlice contains ARP.
45    #[inline]
46    pub fn is_arp(&self) -> bool {
47        use NetSlice::*;
48        matches!(self, Arp(_))
49    }
50
51    /// Returns references to the IPv4 slice if the slice contains an IPv4 values.
52    #[inline]
53    pub fn ipv4_ref(&self) -> Option<&Ipv4Slice<'a>> {
54        if let NetSlice::Ipv4(s) = self {
55            Some(s)
56        } else {
57            None
58        }
59    }
60
61    /// Returns references to the IPv6 slice if the slice contains an IPv6 values.
62    #[inline]
63    pub fn ipv6_ref(&self) -> Option<&Ipv6Slice<'a>> {
64        if let NetSlice::Ipv6(s) = self {
65            Some(s)
66        } else {
67            None
68        }
69    }
70
71    /// Returns references to the ARP packet slice if the slice contains an ARP values.
72    #[inline]
73    pub fn arp_ref(&self) -> Option<&ArpPacketSlice> {
74        if let NetSlice::Arp(arp) = self {
75            Some(arp)
76        } else {
77            None
78        }
79    }
80
81    /// Returns a reference to ip payload if the net slice contains
82    /// an ipv4 or ipv6 slice.
83    #[inline]
84    pub fn ip_payload_ref(&self) -> Option<&IpPayloadSlice<'a>> {
85        match self {
86            NetSlice::Ipv4(s) => Some(&s.payload),
87            NetSlice::Ipv6(s) => Some(&s.payload),
88            NetSlice::Arp(_) => None,
89        }
90    }
91}
92
93impl<'a> From<IpSlice<'a>> for NetSlice<'a> {
94    #[inline]
95    fn from(value: IpSlice<'a>) -> NetSlice<'a> {
96        match value {
97            IpSlice::Ipv4(ipv4) => NetSlice::Ipv4(ipv4),
98            IpSlice::Ipv6(ipv6) => NetSlice::Ipv6(ipv6),
99        }
100    }
101}
102
103impl<'a> From<Ipv4Slice<'a>> for NetSlice<'a> {
104    #[inline]
105    fn from(value: Ipv4Slice<'a>) -> NetSlice<'a> {
106        NetSlice::Ipv4(value)
107    }
108}
109
110impl<'a> From<Ipv6Slice<'a>> for NetSlice<'a> {
111    #[inline]
112    fn from(value: Ipv6Slice<'a>) -> NetSlice<'a> {
113        NetSlice::Ipv6(value)
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use crate::*;
120    use alloc::{format, vec::Vec};
121
122    #[test]
123    fn debug() {
124        let bytes = Ipv6Header {
125            next_header: IpNumber::UDP,
126            ..Default::default()
127        }
128        .to_bytes();
129        let s = Ipv6Slice::from_slice(&bytes).unwrap();
130        let n = NetSlice::Ipv6(s.clone());
131        assert_eq!(format!("{n:?}"), format!("Ipv6({s:?})"));
132    }
133
134    #[test]
135    fn clone_eq() {
136        let bytes = Ipv6Header {
137            next_header: IpNumber::UDP,
138            ..Default::default()
139        }
140        .to_bytes();
141        let s = NetSlice::Ipv6(Ipv6Slice::from_slice(&bytes).unwrap());
142        assert_eq!(s, s.clone())
143    }
144
145    #[test]
146    fn ip_payload_ref_and_is_ip() {
147        // ipv4
148        {
149            let payload = [1, 2, 3, 4];
150            let bytes = {
151                let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
152                bytes.extend_from_slice(
153                    &(Ipv4Header {
154                        total_len: Ipv4Header::MIN_LEN_U16 + 4,
155                        protocol: IpNumber::UDP,
156                        ..Default::default()
157                    })
158                    .to_bytes(),
159                );
160                bytes.extend_from_slice(&payload);
161                bytes
162            };
163            let p = Ipv4Slice::from_slice(&bytes).unwrap();
164            let s = NetSlice::Ipv4(p.clone());
165            assert_eq!(
166                s.ip_payload_ref(),
167                Some(&IpPayloadSlice {
168                    ip_number: IpNumber::UDP,
169                    fragmented: false,
170                    len_source: LenSource::Ipv4HeaderTotalLen,
171                    payload: &payload
172                })
173            );
174            assert!(s.is_ip());
175            assert!(s.is_ipv4());
176            assert_eq!(false, s.is_ipv6());
177            assert_eq!(false, s.is_arp());
178            assert_eq!(Some(&p), s.ipv4_ref());
179            assert_eq!(None, s.ipv6_ref());
180            assert_eq!(None, s.arp_ref());
181        }
182        // ipv6
183        {
184            let payload = [1, 2, 3, 4];
185            let bytes = {
186                let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
187                bytes.extend_from_slice(
188                    &(Ipv6Header {
189                        next_header: IpNumber::UDP,
190                        payload_length: 4,
191                        ..Default::default()
192                    })
193                    .to_bytes(),
194                );
195                bytes.extend_from_slice(&payload);
196                bytes
197            };
198            let p = Ipv6Slice::from_slice(&bytes).unwrap();
199            let s = NetSlice::Ipv6(p.clone());
200            assert_eq!(
201                s.ip_payload_ref(),
202                Some(&IpPayloadSlice {
203                    ip_number: IpNumber::UDP,
204                    fragmented: false,
205                    len_source: LenSource::Ipv6HeaderPayloadLen,
206                    payload: &payload
207                })
208            );
209            assert!(s.is_ip());
210            assert_eq!(false, s.is_ipv4());
211            assert!(s.is_ipv6());
212            assert_eq!(false, s.is_arp());
213            assert_eq!(None, s.ipv4_ref());
214            assert_eq!(Some(&p), s.ipv6_ref());
215            assert_eq!(None, s.arp_ref());
216        }
217        // arp
218        {
219            let arp = ArpPacket::new(
220                ArpHardwareId::ETHERNET,
221                EtherType::IPV4,
222                ArpOperation::REPLY,
223                &[0; 6],
224                &[0; 4],
225                &[0; 6],
226                &[0; 4],
227            )
228            .unwrap();
229            let bytes = arp.to_bytes();
230            let p = ArpPacketSlice::from_slice(&bytes).unwrap();
231            let s = NetSlice::Arp(p.clone());
232            assert_eq!(None, s.ip_payload_ref());
233            assert_eq!(false, s.is_ip());
234            assert_eq!(false, s.is_ipv4());
235            assert_eq!(false, s.is_ipv6());
236            assert!(s.is_arp());
237            assert_eq!(None, s.ipv4_ref());
238            assert_eq!(None, s.ipv6_ref());
239            assert_eq!(Some(&p), s.arp_ref());
240        }
241    }
242
243    #[test]
244    fn from() {
245        // IpSlice::Ipv4
246        {
247            let payload = [1, 2, 3, 4];
248            let bytes = {
249                let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
250                bytes.extend_from_slice(
251                    &(Ipv4Header {
252                        total_len: Ipv4Header::MIN_LEN_U16 + 4,
253                        protocol: IpNumber::UDP,
254                        ..Default::default()
255                    })
256                    .to_bytes(),
257                );
258                bytes.extend_from_slice(&payload);
259                bytes
260            };
261            let i = Ipv4Slice::from_slice(&bytes).unwrap();
262            let actual: NetSlice = IpSlice::Ipv4(i.clone()).into();
263            assert_eq!(NetSlice::Ipv4(i.clone()), actual);
264        }
265        // Ipv4Slice
266        {
267            let payload = [1, 2, 3, 4];
268            let bytes = {
269                let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
270                bytes.extend_from_slice(
271                    &(Ipv4Header {
272                        total_len: Ipv4Header::MIN_LEN_U16 + 4,
273                        protocol: IpNumber::UDP,
274                        ..Default::default()
275                    })
276                    .to_bytes(),
277                );
278                bytes.extend_from_slice(&payload);
279                bytes
280            };
281            let i = Ipv4Slice::from_slice(&bytes).unwrap();
282            let actual: NetSlice = i.clone().into();
283            assert_eq!(NetSlice::Ipv4(i.clone()), actual);
284        }
285        // IpSlice::Ipv6
286        {
287            let payload = [1, 2, 3, 4];
288            let bytes = {
289                let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
290                bytes.extend_from_slice(
291                    &(Ipv6Header {
292                        next_header: IpNumber::UDP,
293                        payload_length: 4,
294                        ..Default::default()
295                    })
296                    .to_bytes(),
297                );
298                bytes.extend_from_slice(&payload);
299                bytes
300            };
301            let i = Ipv6Slice::from_slice(&bytes).unwrap();
302            let actual: NetSlice = i.clone().into();
303            assert_eq!(NetSlice::Ipv6(i.clone()), actual);
304        }
305    }
306}