1use super::address::Ipv6Address;
2use super::builder::Ipv6PacketBuildError;
3use super::next_header::Ipv6NextHeader;
4use crate::error::ParseError;
5
6pub(super) const HEADER_LENGTH: usize = 40;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum Ipv6PayloadLength {
11 Declared(u16),
13 Unspecified,
18}
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
27pub struct Ipv6Packet<'a> {
28 bytes: &'a [u8],
29}
30
31impl<'a> Ipv6Packet<'a> {
32 #[inline]
34 pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
35 let packet_length = validate(bytes)?;
36 Ok(Self {
37 bytes: &bytes[..packet_length],
38 })
39 }
40
41 #[inline]
43 pub fn traffic_class(&self) -> u8 {
44 ((self.bytes[0] & 0x0f) << 4) | (self.bytes[1] >> 4)
45 }
46
47 #[inline]
49 pub fn flow_label(&self) -> u32 {
50 (u32::from(self.bytes[1] & 0x0f) << 16)
51 | (u32::from(self.bytes[2]) << 8)
52 | u32::from(self.bytes[3])
53 }
54
55 #[inline]
57 pub fn payload_length(&self) -> Ipv6PayloadLength {
58 match self.raw_payload_length() {
59 0 => Ipv6PayloadLength::Unspecified,
60 value => Ipv6PayloadLength::Declared(value),
61 }
62 }
63
64 #[inline]
66 pub fn raw_payload_length(&self) -> u16 {
67 u16::from_be_bytes(self.bytes[4..6].try_into().expect("validated IPv6 header"))
68 }
69
70 #[inline]
72 pub fn next_header(&self) -> Ipv6NextHeader {
73 Ipv6NextHeader::new(self.bytes[6])
74 }
75
76 #[inline]
78 pub fn hop_limit(&self) -> u8 {
79 self.bytes[7]
80 }
81
82 #[inline]
84 pub fn source(&self) -> Ipv6Address {
85 Ipv6Address::new(self.bytes[8..24].try_into().expect("validated IPv6 header"))
86 }
87
88 #[inline]
90 pub fn destination(&self) -> Ipv6Address {
91 Ipv6Address::new(
92 self.bytes[24..40]
93 .try_into()
94 .expect("validated IPv6 header"),
95 )
96 }
97
98 #[inline]
104 pub fn payload(&self) -> &'a [u8] {
105 &self.bytes[HEADER_LENGTH..]
106 }
107
108 #[inline]
110 pub fn as_bytes(&self) -> &'a [u8] {
111 self.bytes
112 }
113}
114
115#[derive(Debug, Eq, PartialEq)]
117pub struct Ipv6PacketMut<'a> {
118 bytes: &'a mut [u8],
119}
120
121impl<'a> Ipv6PacketMut<'a> {
122 #[inline]
124 pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
125 let packet_length = validate(bytes)?;
126 Ok(Self::from_validated(&mut bytes[..packet_length]))
127 }
128
129 pub(super) fn from_validated(bytes: &'a mut [u8]) -> Self {
130 Self { bytes }
131 }
132
133 #[inline]
135 pub fn traffic_class(&self) -> u8 {
136 ((self.bytes[0] & 0x0f) << 4) | (self.bytes[1] >> 4)
137 }
138
139 #[inline]
141 pub fn flow_label(&self) -> u32 {
142 (u32::from(self.bytes[1] & 0x0f) << 16)
143 | (u32::from(self.bytes[2]) << 8)
144 | u32::from(self.bytes[3])
145 }
146
147 #[inline]
149 pub fn payload_length(&self) -> Ipv6PayloadLength {
150 match self.raw_payload_length() {
151 0 => Ipv6PayloadLength::Unspecified,
152 value => Ipv6PayloadLength::Declared(value),
153 }
154 }
155
156 #[inline]
158 pub fn raw_payload_length(&self) -> u16 {
159 u16::from_be_bytes(self.bytes[4..6].try_into().expect("validated IPv6 header"))
160 }
161
162 #[inline]
164 pub fn next_header(&self) -> Ipv6NextHeader {
165 Ipv6NextHeader::new(self.bytes[6])
166 }
167
168 #[inline]
170 pub fn hop_limit(&self) -> u8 {
171 self.bytes[7]
172 }
173
174 #[inline]
176 pub fn source(&self) -> Ipv6Address {
177 Ipv6Address::new(self.bytes[8..24].try_into().expect("validated IPv6 header"))
178 }
179
180 #[inline]
182 pub fn destination(&self) -> Ipv6Address {
183 Ipv6Address::new(
184 self.bytes[24..40]
185 .try_into()
186 .expect("validated IPv6 header"),
187 )
188 }
189
190 #[inline]
192 pub fn payload(&self) -> &[u8] {
193 &self.bytes[HEADER_LENGTH..]
194 }
195
196 #[inline]
198 pub fn payload_mut(&mut self) -> &mut [u8] {
199 &mut self.bytes[HEADER_LENGTH..]
200 }
201
202 #[inline]
204 pub fn as_bytes(&self) -> &[u8] {
205 self.bytes
206 }
207
208 #[inline]
210 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
211 self.bytes
212 }
213
214 #[inline]
216 pub fn set_traffic_class(&mut self, value: u8) {
217 self.bytes[0] = (self.bytes[0] & 0xf0) | (value >> 4);
218 self.bytes[1] = (self.bytes[1] & 0x0f) | (value << 4);
219 }
220
221 #[inline]
223 pub fn set_flow_label(&mut self, value: u32) -> Result<(), Ipv6PacketBuildError> {
224 if value > 0x000f_ffff {
225 return Err(Ipv6PacketBuildError::FlowLabelTooLarge);
226 }
227 self.bytes[1] = (self.bytes[1] & 0xf0) | ((value >> 16) as u8);
228 self.bytes[2] = (value >> 8) as u8;
229 self.bytes[3] = value as u8;
230 Ok(())
231 }
232
233 #[inline]
235 pub fn set_next_header(&mut self, value: Ipv6NextHeader) {
236 self.bytes[6] = value.raw();
237 }
238
239 #[inline]
241 pub fn set_hop_limit(&mut self, value: u8) {
242 self.bytes[7] = value;
243 }
244
245 #[inline]
247 pub fn set_source(&mut self, value: Ipv6Address) {
248 self.bytes[8..24].copy_from_slice(&value.octets());
249 }
250
251 #[inline]
253 pub fn set_destination(&mut self, value: Ipv6Address) {
254 self.bytes[24..40].copy_from_slice(&value.octets());
255 }
256}
257
258#[inline]
259fn validate(bytes: &[u8]) -> Result<usize, ParseError> {
260 if bytes.len() < HEADER_LENGTH {
261 return Err(ParseError::Truncated {
262 minimum: HEADER_LENGTH,
263 available: bytes.len(),
264 });
265 }
266 let version = bytes[0] >> 4;
267 if version != 6 {
268 return Err(ParseError::InvalidVersion {
269 expected: 6,
270 actual: version,
271 });
272 }
273 let payload_length = usize::from(u16::from_be_bytes(
274 bytes[4..6].try_into().expect("validated IPv6 header"),
275 ));
276 if payload_length == 0 {
277 return Ok(bytes.len());
278 }
279 let packet_length = HEADER_LENGTH + payload_length;
280 if bytes.len() < packet_length {
281 return Err(ParseError::Truncated {
282 minimum: packet_length,
283 available: bytes.len(),
284 });
285 }
286 Ok(packet_length)
287}