mutnet/ipv6_extensions/
method_traits.rs

1//! IPv6 extensions access and manipulation methods.
2
3use core::cmp::Ordering;
4
5use crate::data_buffer::traits::{
6    BufferAccess, BufferAccessMut, HeaderManipulation, HeaderMetadata, Layer,
7};
8use crate::ipv6::UpdateIpv6Length;
9use crate::ipv6_extensions::metadata_trait::{Ipv6ExtMetaData, Ipv6ExtMetaDataMut};
10use crate::ipv6_extensions::{
11    Ipv6ExtFieldError, Ipv6ExtSetFieldError, Ipv6ExtTypedHeaderError,
12    Ipv6ExtensionIndexOutOfBoundsError, Ipv6ExtensionType,
13};
14use crate::typed_protocol_headers::InternetProtocolNumber;
15use crate::typed_protocol_headers::RoutingType;
16
17pub(crate) static NEXT_HEADER: usize = 0;
18pub(crate) static EXTENSION_MIN_LEN: usize = 8;
19
20mod shared_dest_opt_hop_by_hop_routing {
21    pub(crate) static LENGTH: usize = 1;
22}
23
24mod dest_opt_and_hop_by_hop {
25    pub(crate) static DATA_START: usize = 2;
26}
27
28mod routing {
29    pub(crate) static ROUTING_TYPE: usize = 2;
30    pub(crate) static SEGMENTS_LEFT: usize = 3;
31    pub(crate) static DATA_START: usize = 4;
32}
33
34mod fragment {
35    use core::ops::Range;
36
37    pub(crate) static FRAGMENT_OFFSET: Range<usize> = 2..4;
38    pub(crate) static FRAGMENT_OFFSET_SHIFT: usize = 3;
39    pub(crate) static MORE_FRAGMENTS_BYTE: usize = 3;
40    pub(crate) static MORE_FRAGMENTS_MASK: u8 = 0b0000_0001;
41    pub(crate) static IDENTIFICATION: Range<usize> = 4..8;
42}
43
44pub(crate) static LAYER: Layer = Layer::Ipv6Ext;
45
46// Length manipulating methods:
47// - set_ipv6_ext_length (has proof)
48
49/// Methods available for [`DataBuffer`](crate::data_buffer::DataBuffer) containing an
50/// [`Ipv6Extensions`](crate::ipv6_extensions::Ipv6Extensions) header.
51///
52/// `MAX_EXTENSIONS` defines the maximum amount of extensions that will be parsed.
53#[allow(private_bounds)]
54pub trait Ipv6ExtMethods<const MAX_EXTENSIONS: usize>:
55    HeaderMetadata + BufferAccess + Ipv6ExtMetaData<MAX_EXTENSIONS>
56{
57    /// Returns the amount of IPv6 extensions.
58    #[inline]
59    fn ipv6_ext_amount(&self) -> usize {
60        self.extensions_amount()
61    }
62
63    /// Returns an array containing all IPv6 extensions.
64    ///
65    /// `None` signals less than the `MAX_EXTENSIONS` amount of IPv6 extensions were present.
66    /// The length of the array is defined by the maximum amount of parsed extensions.
67    #[inline]
68    fn ipv6_extensions(&self) -> [Option<Ipv6ExtensionType>; MAX_EXTENSIONS] {
69        let mut result = [None; MAX_EXTENSIONS];
70        self.extensions_array()[..self.extensions_amount()]
71            .iter()
72            .enumerate()
73            .for_each(|(i, ext)| result[i] = Some(ext.ext_type));
74        result
75    }
76
77    /// Returns the last extension's next header.
78    ///
79    /// # Errors
80    /// Returns an error if no extension was parsed.
81    #[inline]
82    fn ipv6_ext_next_header(&self) -> Result<u8, Ipv6ExtensionIndexOutOfBoundsError> {
83        let extension_metadata = self.extension(self.extensions_amount().saturating_sub(1))?;
84        Ok(self.read_value(LAYER, extension_metadata.offset + NEXT_HEADER))
85    }
86
87    /// Returns the last extension's next header as [`InternetProtocolNumber`].
88    ///
89    /// # Errors
90    /// Returns an error if:
91    /// - no extension was parsed.
92    /// - the next header is not recognized.
93    #[inline]
94    fn ipv6_ext_typed_next_header(
95        &self,
96    ) -> Result<InternetProtocolNumber, Ipv6ExtTypedHeaderError> {
97        Ok(self.ipv6_ext_next_header()?.try_into()?)
98    }
99
100    /// Returns the next header of the extension at `extension_index`.
101    ///
102    /// Indexing starts at zero.
103    ///
104    /// Method available for all extensions.
105    ///
106    /// # Errors
107    /// Returns an error if `extension_index` does not map to a parsed extension (out of bounds).
108    #[inline]
109    fn ipv6_ext_per_extension_next_header(
110        &self,
111        extension_index: usize,
112    ) -> Result<u8, Ipv6ExtensionIndexOutOfBoundsError> {
113        let extension_metadata = self.extension(extension_index)?;
114        Ok(self.read_value(LAYER, extension_metadata.offset + NEXT_HEADER))
115    }
116
117    /// Returns the next header of the extension at `extension_index` as [`InternetProtocolNumber`].
118    ///
119    /// Indexing starts at zero.
120    ///
121    /// Method available for all extensions.
122    ///
123    /// # Errors
124    /// Returns an error if:
125    /// - `extension_index` does not map to a parsed extension (out of bounds).
126    /// - the next header is not recognized.
127    #[inline]
128    fn ipv6_ext_per_extension_typed_next_header(
129        &self,
130        extension_index: usize,
131    ) -> Result<InternetProtocolNumber, Ipv6ExtTypedHeaderError> {
132        Ok(self
133            .ipv6_ext_per_extension_next_header(extension_index)?
134            .try_into()?)
135    }
136
137    /// Returns the length field of the extension at `extension_index`.
138    ///
139    /// Indexing starts at zero.
140    ///
141    /// Method available for routing, destination options, hop by hop extensions.
142    ///
143    /// # Errors
144    /// Returns an error if:
145    /// - `extension_index` does not map to a parsed extension (out of bounds).
146    /// - the extension does not have the requested field.
147    #[inline]
148    fn ipv6_ext_length(&self, extension_index: usize) -> Result<u8, Ipv6ExtFieldError> {
149        let extension_metadata = self.extension(extension_index)?;
150        match extension_metadata.ext_type {
151            Ipv6ExtensionType::Fragment => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
152            Ipv6ExtensionType::DestinationOptions
153            | Ipv6ExtensionType::HopByHop
154            | Ipv6ExtensionType::Routing => Ok(self.read_value(
155                LAYER,
156                extension_metadata.offset + shared_dest_opt_hop_by_hop_routing::LENGTH,
157            )),
158        }
159    }
160
161    /// Returns the length of the extension at `extension_index` in bytes.
162    ///
163    /// Indexing starts at zero.
164    ///
165    /// Method available for all extensions.
166    ///
167    /// # Errors
168    /// Returns an error if `extension_index` does not map to a parsed extension (out of bounds).
169    #[inline]
170    fn ipv6_ext_length_in_bytes(
171        &self,
172        extension_index: usize,
173    ) -> Result<usize, Ipv6ExtensionIndexOutOfBoundsError> {
174        let extension_metadata = self.extension(extension_index)?;
175        match extension_metadata.ext_type {
176            Ipv6ExtensionType::Fragment => Ok(8),
177            Ipv6ExtensionType::DestinationOptions
178            | Ipv6ExtensionType::HopByHop
179            | Ipv6ExtensionType::Routing => Ok((usize::from(self.read_value(
180                LAYER,
181                extension_metadata.offset + shared_dest_opt_hop_by_hop_routing::LENGTH,
182            )) + 1)
183                * 8),
184        }
185    }
186
187    /// Returns a slice containing the data of the extension at `extension_index`.
188    ///
189    /// Indexing starts at zero.
190    ///
191    /// Method available for routing, destination options, hop by hop extensions.
192    ///
193    /// # Errors
194    /// Returns an error if:
195    /// - `extension_index` does not map to a parsed extension (out of bounds).
196    /// - the extension does not have the requested field.
197    #[inline]
198    fn ipv6_ext_data(&self, extension_index: usize) -> Result<&[u8], Ipv6ExtFieldError> {
199        let extension_metadata = self.extension(extension_index)?;
200        let data_range = match extension_metadata.ext_type {
201            Ipv6ExtensionType::Fragment => return Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
202            Ipv6ExtensionType::Routing => {
203                let data_end = self.ipv6_ext_length_in_bytes(extension_index)?;
204                extension_metadata.offset + routing::DATA_START
205                    ..extension_metadata.offset + data_end
206            }
207            Ipv6ExtensionType::DestinationOptions | Ipv6ExtensionType::HopByHop => {
208                let data_end = self.ipv6_ext_length_in_bytes(extension_index)?;
209                extension_metadata.offset + dest_opt_and_hop_by_hop::DATA_START
210                    ..extension_metadata.offset + data_end
211            }
212        };
213        Ok(self.read_slice(LAYER, data_range))
214    }
215
216    /// Returns the routing type of the extension at `extension_index`.
217    ///
218    /// Indexing starts at zero.
219    ///
220    /// Method available for routing extensions.
221    ///
222    /// # Errors
223    /// Returns an error if:
224    /// - `extension_index` does not map to a parsed extension (out of bounds).
225    /// - the extension does not have the requested field.
226    #[inline]
227    fn ipv6_ext_routing_type(&self, extension_index: usize) -> Result<u8, Ipv6ExtFieldError> {
228        let extension_metadata = self.extension(extension_index)?;
229        match extension_metadata.ext_type {
230            Ipv6ExtensionType::Routing => {
231                Ok(self.read_value(LAYER, extension_metadata.offset + routing::ROUTING_TYPE))
232            }
233            Ipv6ExtensionType::DestinationOptions
234            | Ipv6ExtensionType::HopByHop
235            | Ipv6ExtensionType::Fragment => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
236        }
237    }
238
239    /// Returns the segments left of the extension at `extension_index`.
240    ///
241    /// Indexing starts at zero.
242    ///
243    /// Method available for routing extensions.
244    ///
245    /// # Errors
246    /// Returns an error if:
247    /// - `extension_index` does not map to a parsed extension (out of bounds).
248    /// - the extension does not have the requested field.
249    #[inline]
250    fn ipv6_ext_segments_left(&self, extension_index: usize) -> Result<u8, Ipv6ExtFieldError> {
251        let extension_metadata = self.extension(extension_index)?;
252        match extension_metadata.ext_type {
253            Ipv6ExtensionType::Routing => {
254                Ok(self.read_value(LAYER, extension_metadata.offset + routing::SEGMENTS_LEFT))
255            }
256            Ipv6ExtensionType::DestinationOptions
257            | Ipv6ExtensionType::HopByHop
258            | Ipv6ExtensionType::Fragment => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
259        }
260    }
261
262    /// Returns the fragment offset of the extension at `extension_index`.
263    ///
264    /// Indexing starts at zero.
265    ///
266    /// Method available for fragment extensions.
267    ///
268    /// # Errors
269    /// Returns an error if:
270    /// - `extension_index` does not map to a parsed extension (out of bounds).
271    /// - the extension does not have the requested field.
272    #[inline]
273    fn ipv6_ext_fragment_offset(&self, extension_index: usize) -> Result<u16, Ipv6ExtFieldError> {
274        let extension_metadata = self.extension(extension_index)?;
275        match extension_metadata.ext_type {
276            Ipv6ExtensionType::Fragment => Ok(u16::from_be_bytes(self.read_array(
277                LAYER,
278                extension_metadata.offset + fragment::FRAGMENT_OFFSET.start
279                    ..extension_metadata.offset + fragment::FRAGMENT_OFFSET.end,
280            )) >> fragment::FRAGMENT_OFFSET_SHIFT),
281            Ipv6ExtensionType::DestinationOptions
282            | Ipv6ExtensionType::HopByHop
283            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
284        }
285    }
286
287    /// Returns the more fragments flag of the extension at `extension_index`.
288    ///
289    /// Indexing starts at zero.
290    ///
291    /// Method available for fragment extensions.
292    ///
293    /// # Errors
294    /// Returns an error if:
295    /// - `extension_index` does not map to a parsed extension (out of bounds).
296    /// - the extension does not have the requested field.
297    #[inline]
298    fn ipv6_ext_more_fragments(&self, extension_index: usize) -> Result<bool, Ipv6ExtFieldError> {
299        let extension_metadata = self.extension(extension_index)?;
300        match extension_metadata.ext_type {
301            Ipv6ExtensionType::Fragment => Ok((self.read_value(
302                LAYER,
303                extension_metadata.offset + fragment::MORE_FRAGMENTS_BYTE,
304            ) & fragment::MORE_FRAGMENTS_MASK)
305                != 0),
306            Ipv6ExtensionType::DestinationOptions
307            | Ipv6ExtensionType::HopByHop
308            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
309        }
310    }
311
312    /// Returns the fragment identification of the extension at `extension_index`.
313    ///
314    /// Indexing starts at zero.
315    ///
316    /// Method available for fragment extensions.
317    ///
318    /// # Errors
319    /// Returns an error if:
320    /// - `extension_index` does not map to a parsed extension (out of bounds).
321    /// - the extension does not have the requested field.
322    #[inline]
323    fn ipv6_ext_fragment_identification(
324        &self,
325        extension_index: usize,
326    ) -> Result<u32, Ipv6ExtFieldError> {
327        let extension_metadata = self.extension(extension_index)?;
328        match extension_metadata.ext_type {
329            Ipv6ExtensionType::Fragment => Ok(u32::from_be_bytes(self.read_array(
330                LAYER,
331                extension_metadata.offset + fragment::IDENTIFICATION.start
332                    ..extension_metadata.offset + fragment::IDENTIFICATION.end,
333            ))),
334            Ipv6ExtensionType::DestinationOptions
335            | Ipv6ExtensionType::HopByHop
336            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
337        }
338    }
339}
340
341/// Methods available for [`DataBuffer`](crate::data_buffer::DataBuffer) containing an
342/// [`Ipv6Extensions`](crate::ipv6_extensions::Ipv6Extensions) header and wrapping a mutable data buffer.
343#[allow(private_bounds)]
344pub trait Ipv6ExtMethodsMut<const MAX_EXTENSIONS: usize>:
345    HeaderMetadata
346    + HeaderManipulation
347    + BufferAccessMut
348    + Ipv6ExtMethods<MAX_EXTENSIONS>
349    + Ipv6ExtMetaData<MAX_EXTENSIONS>
350    + Ipv6ExtMetaDataMut<MAX_EXTENSIONS>
351    + UpdateIpv6Length
352    + Sized
353{
354    /// Sets the last extension's next header.
355    ///
356    /// # Errors
357    /// Returns an error if no extension was parsed.
358    #[inline]
359    fn set_ipv6_ext_next_header(
360        &mut self,
361        next_header: InternetProtocolNumber,
362    ) -> Result<(), Ipv6ExtensionIndexOutOfBoundsError> {
363        let extension_metadata = self.extension(self.extensions_amount().saturating_sub(1))?;
364        self.write_value(
365            LAYER,
366            extension_metadata.offset + NEXT_HEADER,
367            next_header as u8,
368        );
369        Ok(())
370    }
371
372    /// Sets the extension's length of the extension at `extension_index`.
373    ///
374    /// Indexing starts at zero.
375    ///
376    /// Method available for routing, destination options, hop by hop extensions.
377    ///
378    /// This takes lower layers into account.
379    /// If there is an [`IPv4`](crate::ipv4::Ipv4) or [`IPv6`](crate::ipv6::Ipv6) layer present,
380    /// the length of that header will be updated accordingly.
381    ///
382    /// # Errors
383    /// Returns an error if:
384    /// - `extension_index` does not map to a parsed extension (out of bounds).
385    /// - the extension does not have the requested field.
386    /// - there is not enough headroom available to accommodate the size change.
387    #[inline]
388    fn set_ipv6_ext_length(
389        &mut self,
390        new_length: u8,
391        extension_index: usize,
392    ) -> Result<(), Ipv6ExtSetFieldError> {
393        let extension_metadata = self.extension(extension_index)?;
394
395        match extension_metadata.ext_type {
396            Ipv6ExtensionType::Fragment => Err(Ipv6ExtSetFieldError::HeaderFieldDoesNotExist),
397            Ipv6ExtensionType::DestinationOptions
398            | Ipv6ExtensionType::HopByHop
399            | Ipv6ExtensionType::Routing => {
400                let new_length_in_bytes = (usize::from(new_length) + 1) * 8;
401                let old_length_in_bytes = self.ipv6_ext_length_in_bytes(extension_index)?;
402
403                match old_length_in_bytes.cmp(&new_length_in_bytes) {
404                    Ordering::Less => {
405                        let difference = new_length_in_bytes - old_length_in_bytes;
406                        self.grow_header(
407                            extension_metadata.offset + old_length_in_bytes,
408                            difference,
409                            LAYER,
410                        )?;
411                        let extensions_amount = self.extensions_amount();
412                        self.extensions_array_mut()[extension_index + 1..extensions_amount]
413                            .iter_mut()
414                            .for_each(|extension_metadata| {
415                                extension_metadata.offset += difference;
416                            });
417                    }
418                    Ordering::Equal => return Ok(()),
419                    Ordering::Greater => {
420                        let difference = old_length_in_bytes - new_length_in_bytes;
421                        self.shrink_header(
422                            extension_metadata.offset + new_length_in_bytes,
423                            difference,
424                            LAYER,
425                        );
426                        let extensions_amount = self.extensions_amount();
427                        self.extensions_array_mut()[extension_index + 1..extensions_amount]
428                            .iter_mut()
429                            .for_each(|extension_metadata| {
430                                extension_metadata.offset -= difference;
431                            });
432                    }
433                }
434
435                self.update_ipv6_length();
436                self.write_value(
437                    LAYER,
438                    extension_metadata.offset + shared_dest_opt_hop_by_hop_routing::LENGTH,
439                    new_length,
440                );
441                Ok(())
442            }
443        }
444    }
445
446    /// Returns a mutable slice containing the data of the extension at `extension_index`.
447    ///
448    /// Indexing starts at zero.
449    ///
450    /// Method available for routing, destination options, hop by hop extensions.
451    ///
452    /// # Errors
453    /// Returns an error if:
454    /// - `extension_index` does not map to a parsed extension (out of bounds).
455    /// - the extension does not have the requested field.
456    #[inline]
457    fn ipv6_ext_data_mut(
458        &mut self,
459        extension_index: usize,
460    ) -> Result<&mut [u8], Ipv6ExtFieldError> {
461        let extension_metadata = self.extension(extension_index)?;
462        let data_range = match extension_metadata.ext_type {
463            Ipv6ExtensionType::Fragment => return Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
464            Ipv6ExtensionType::Routing => {
465                let data_end = self.ipv6_ext_length_in_bytes(extension_index)?;
466                extension_metadata.offset + routing::DATA_START
467                    ..extension_metadata.offset + data_end
468            }
469            Ipv6ExtensionType::DestinationOptions | Ipv6ExtensionType::HopByHop => {
470                let data_end = self.ipv6_ext_length_in_bytes(extension_index)?;
471                extension_metadata.offset + dest_opt_and_hop_by_hop::DATA_START
472                    ..extension_metadata.offset + data_end
473            }
474        };
475        Ok(self.get_slice_mut(LAYER, data_range))
476    }
477
478    /// Sets the routing type of the extension at `extension_index`.
479    ///
480    /// Indexing starts at zero.
481    ///
482    /// Method available for routing extensions.
483    ///
484    /// # Errors
485    /// Returns an error if:
486    /// - `extension_index` does not map to a parsed extension (out of bounds).
487    /// - the extension does not have the requested field.
488    #[inline]
489    fn set_ipv6_ext_routing_type(
490        &mut self,
491        routing_type: RoutingType,
492        extension_index: usize,
493    ) -> Result<(), Ipv6ExtFieldError> {
494        let extension_metadata = self.extension(extension_index)?;
495        match extension_metadata.ext_type {
496            Ipv6ExtensionType::Routing => {
497                self.write_value(
498                    LAYER,
499                    extension_metadata.offset + routing::ROUTING_TYPE,
500                    routing_type as u8,
501                );
502                Ok(())
503            }
504            Ipv6ExtensionType::DestinationOptions
505            | Ipv6ExtensionType::HopByHop
506            | Ipv6ExtensionType::Fragment => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
507        }
508    }
509
510    /// Sets the segments left of the extension at `extension_index`.
511    ///
512    /// Indexing starts at zero.
513    ///
514    /// Method available for routing extensions.
515    ///
516    /// # Errors
517    /// Returns an error if:
518    /// - `extension_index` does not map to a parsed extension (out of bounds).
519    /// - the extension does not have the requested field.
520    #[inline]
521    fn set_ipv6_ext_segments_left(
522        &mut self,
523        segments_left: u8,
524        extension_index: usize,
525    ) -> Result<(), Ipv6ExtFieldError> {
526        let extension_metadata = self.extension(extension_index)?;
527        match extension_metadata.ext_type {
528            Ipv6ExtensionType::Routing => {
529                self.write_value(
530                    LAYER,
531                    extension_metadata.offset + routing::SEGMENTS_LEFT,
532                    segments_left,
533                );
534                Ok(())
535            }
536            Ipv6ExtensionType::DestinationOptions
537            | Ipv6ExtensionType::HopByHop
538            | Ipv6ExtensionType::Fragment => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
539        }
540    }
541
542    /// Sets the fragment offset of the extension at `extension_index`.
543    ///
544    /// Indexing starts at zero.
545    ///
546    /// Method available for fragment extensions.
547    ///
548    /// # Errors
549    /// Returns an error if:
550    /// - `extension_index` does not map to a parsed extension (out of bounds).
551    /// - the extension does not have the requested field.
552    #[inline]
553    fn set_ipv6_ext_fragment_offset(
554        &mut self,
555        mut fragment_offset: u16,
556        extension_index: usize,
557    ) -> Result<(), Ipv6ExtFieldError> {
558        let extension_metadata = self.extension(extension_index)?;
559        match extension_metadata.ext_type {
560            Ipv6ExtensionType::Fragment => {
561                fragment_offset <<= fragment::FRAGMENT_OFFSET_SHIFT;
562                fragment_offset |= u16::from(
563                    self.read_value(LAYER, fragment::MORE_FRAGMENTS_BYTE)
564                        & fragment::MORE_FRAGMENTS_MASK,
565                );
566
567                self.write_slice(
568                    LAYER,
569                    extension_metadata.offset + fragment::FRAGMENT_OFFSET.start
570                        ..extension_metadata.offset + fragment::FRAGMENT_OFFSET.end,
571                    &fragment_offset.to_be_bytes(),
572                );
573
574                Ok(())
575            }
576            Ipv6ExtensionType::DestinationOptions
577            | Ipv6ExtensionType::HopByHop
578            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
579        }
580    }
581
582    /// Sets the more fragments flag of the extension at `extension_index`.
583    ///
584    /// Indexing starts at zero.
585    ///
586    /// Method available for fragment extensions.
587    ///
588    /// # Errors
589    /// Returns an error if:
590    /// - `extension_index` does not map to a parsed extension (out of bounds).
591    /// - the extension does not have the requested field.
592    #[inline]
593    fn set_ipv6_ext_more_fragments(
594        &mut self,
595        more_fragments: bool,
596        extension_index: usize,
597    ) -> Result<(), Ipv6ExtFieldError> {
598        let extension_metadata = self.extension(extension_index)?;
599        match extension_metadata.ext_type {
600            Ipv6ExtensionType::Fragment => {
601                let byte_to_set = (self.read_value(LAYER, fragment::MORE_FRAGMENTS_BYTE)
602                    & !fragment::MORE_FRAGMENTS_MASK)
603                    | u8::from(more_fragments);
604                self.write_value(
605                    LAYER,
606                    extension_metadata.offset + fragment::MORE_FRAGMENTS_BYTE,
607                    byte_to_set,
608                );
609
610                Ok(())
611            }
612            Ipv6ExtensionType::DestinationOptions
613            | Ipv6ExtensionType::HopByHop
614            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
615        }
616    }
617
618    /// Sets the fragment identification of the extension at `extension_index`.
619    ///
620    /// Indexing starts at zero.
621    ///
622    /// Method available for fragment extensions.
623    ///
624    /// # Errors
625    /// Returns an error if:
626    /// - `extension_index` does not map to a parsed extension (out of bounds).
627    /// - the extension does not have the requested field.
628    #[inline]
629    fn set_ipv6_ext_fragment_identification(
630        &mut self,
631        identification: u32,
632        extension_index: usize,
633    ) -> Result<(), Ipv6ExtFieldError> {
634        let extension_metadata = self.extension(extension_index)?;
635        match extension_metadata.ext_type {
636            Ipv6ExtensionType::Fragment => {
637                self.write_slice(
638                    LAYER,
639                    extension_metadata.offset + fragment::IDENTIFICATION.start
640                        ..extension_metadata.offset + fragment::IDENTIFICATION.end,
641                    &identification.to_be_bytes(),
642                );
643                Ok(())
644            }
645            Ipv6ExtensionType::DestinationOptions
646            | Ipv6ExtensionType::HopByHop
647            | Ipv6ExtensionType::Routing => Err(Ipv6ExtFieldError::HeaderFieldDoesNotExist),
648        }
649    }
650}