Skip to main content

net_wire/ipv6/
dispatch.rs

1//! IPv6 concrete upper-layer dispatch after extension-header traversal.
2
3use super::error::Ipv6DispatchError;
4use super::extensions;
5use super::next_header::Ipv6NextHeader;
6use super::packet::{Ipv6Packet, Ipv6PacketMut};
7#[cfg(feature = "icmpv6")]
8use crate::icmpv6::message::{Icmpv6Message, Icmpv6MessageMut};
9#[cfg(feature = "tcp")]
10use crate::tcp::segment::{TcpSegment, TcpSegmentMut};
11#[cfg(feature = "udp")]
12use crate::udp::datagram::{UdpDatagram, UdpDatagramMut};
13
14impl<'a> Ipv6Packet<'a> {
15    /// Parses ICMPv6 after traversing supported IPv6 extension headers.
16    #[cfg(feature = "icmpv6")]
17    #[inline]
18    pub fn icmpv6(&self) -> Result<Option<Icmpv6Message<'a>>, Ipv6DispatchError> {
19        let traversal = extensions::traverse(
20            self.next_header(),
21            self.raw_payload_length(),
22            self.payload(),
23        )
24        .map_err(Ipv6DispatchError::Traversal)?;
25        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::ICMPV6.raw() {
26            return Ok(None);
27        }
28        Icmpv6Message::parse(&self.payload()[traversal.upper_offset..])
29            .map(Some)
30            .map_err(Ipv6DispatchError::UpperLayer)
31    }
32
33    /// Parses UDP after traversing supported IPv6 extension headers.
34    #[cfg(feature = "udp")]
35    #[inline]
36    pub fn udp(&self) -> Result<Option<UdpDatagram<'a>>, Ipv6DispatchError> {
37        let traversal = extensions::traverse(
38            self.next_header(),
39            self.raw_payload_length(),
40            self.payload(),
41        )
42        .map_err(Ipv6DispatchError::Traversal)?;
43        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::UDP.raw() {
44            return Ok(None);
45        }
46        UdpDatagram::parse(&self.payload()[traversal.upper_offset..])
47            .map(Some)
48            .map_err(Ipv6DispatchError::UpperLayer)
49    }
50
51    /// Parses TCP after traversing supported IPv6 extension headers.
52    #[cfg(feature = "tcp")]
53    #[inline]
54    pub fn tcp(&self) -> Result<Option<TcpSegment<'a>>, Ipv6DispatchError> {
55        let traversal = extensions::traverse(
56            self.next_header(),
57            self.raw_payload_length(),
58            self.payload(),
59        )
60        .map_err(Ipv6DispatchError::Traversal)?;
61        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::TCP.raw() {
62            return Ok(None);
63        }
64        TcpSegment::parse(&self.payload()[traversal.upper_offset..])
65            .map(Some)
66            .map_err(Ipv6DispatchError::UpperLayer)
67    }
68}
69
70impl<'a> Ipv6PacketMut<'a> {
71    /// Parses mutable ICMPv6 after traversing supported IPv6 extension headers.
72    #[cfg(feature = "icmpv6")]
73    #[inline]
74    pub fn icmpv6_mut(&mut self) -> Result<Option<Icmpv6MessageMut<'_>>, Ipv6DispatchError> {
75        let traversal = extensions::traverse(
76            self.next_header(),
77            self.raw_payload_length(),
78            self.payload(),
79        )
80        .map_err(Ipv6DispatchError::Traversal)?;
81        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::ICMPV6.raw() {
82            return Ok(None);
83        }
84        Icmpv6MessageMut::parse(&mut self.payload_mut()[traversal.upper_offset..])
85            .map(Some)
86            .map_err(Ipv6DispatchError::UpperLayer)
87    }
88
89    /// Parses mutable UDP after traversing supported IPv6 extension headers.
90    #[cfg(feature = "udp")]
91    #[inline]
92    pub fn udp_mut(&mut self) -> Result<Option<UdpDatagramMut<'_>>, Ipv6DispatchError> {
93        let traversal = extensions::traverse(
94            self.next_header(),
95            self.raw_payload_length(),
96            self.payload(),
97        )
98        .map_err(Ipv6DispatchError::Traversal)?;
99        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::UDP.raw() {
100            return Ok(None);
101        }
102        UdpDatagramMut::parse(&mut self.payload_mut()[traversal.upper_offset..])
103            .map(Some)
104            .map_err(Ipv6DispatchError::UpperLayer)
105    }
106
107    /// Parses mutable TCP after traversing supported IPv6 extension headers.
108    #[cfg(feature = "tcp")]
109    #[inline]
110    pub fn tcp_mut(&mut self) -> Result<Option<TcpSegmentMut<'_>>, Ipv6DispatchError> {
111        let traversal = extensions::traverse(
112            self.next_header(),
113            self.raw_payload_length(),
114            self.payload(),
115        )
116        .map_err(Ipv6DispatchError::Traversal)?;
117        if traversal.non_atomic_fragment || traversal.next_header != Ipv6NextHeader::TCP.raw() {
118            return Ok(None);
119        }
120        TcpSegmentMut::parse(&mut self.payload_mut()[traversal.upper_offset..])
121            .map(Some)
122            .map_err(Ipv6DispatchError::UpperLayer)
123    }
124}