Files
firezone/rust/connlib/etherparse-ext/src/ipv6_header_slice_mut.rs
Thomas Eizinger 5566f1847f refactor(rust): move crates into a more sensical hierarchy (#9066)
The current `rust/` directory is a bit of a wild-west in terms of how
the crates are organised. Most of them are simply at the top-level when
in reality, they are all `connlib`-related. The Apple and Android FFI
crates - which are entrypoints in the Rust code are defined several
layers deep.

To improve the situation, we move around and rename several crates. The
end result is that all top-level crates / directories are:

- Either entrypoints into the Rust code, i.e. applications such as
Gateway, Relay or a Client
- Or crates shared across all those entrypoints, such as `telemetry` or
`logging`
2025-05-12 01:04:17 +00:00

51 lines
1.8 KiB
Rust

use crate::slice_utils::write_to_offset_unchecked;
use etherparse::Ipv6HeaderSlice;
pub struct Ipv6HeaderSliceMut<'a> {
slice: &'a mut [u8],
}
impl<'a> Ipv6HeaderSliceMut<'a> {
/// Creates a new [`Ipv6HeaderSliceMut`].
pub fn from_slice(
slice: &'a mut [u8],
) -> Result<Self, etherparse::err::ipv6::HeaderSliceError> {
Ipv6HeaderSlice::from_slice(slice)?;
Ok(Self { slice })
}
pub fn set_source(&mut self, src: [u8; 16]) {
// Safety: Slice it at least of length 40 as checked in the ctor.
unsafe { write_to_offset_unchecked(self.slice, 8, src) };
}
pub fn set_destination(&mut self, dst: [u8; 16]) {
// Safety: Slice it at least of length 40 as checked in the ctor.
unsafe { write_to_offset_unchecked(self.slice, 24, dst) };
}
/// Sets the ECN bits in the IPv6 header.
///
/// Doing this is a bit trickier than for IPv4 due to the layout of the IPv6 header:
///
/// ```text
/// 0 8 16 24 32
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// |Version| Traffic Class | Flow Label |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// ```
///
/// The Traffic Class field (of which the lower two bits are used for ECN) is split across
/// two bytes. Thus, to set the ECN bits, we actually need to set bit 3 & 4 of the second byte.
pub fn set_ecn(&mut self, ecn: u8) {
let mask = 0b1100_1111; // Mask to clear the ecn bits.
let ecn = ecn << 4; // Shift the ecn bits to the correct position (so they fit the mask above).
let second_byte = self.slice[1];
let new = second_byte & mask | ecn;
unsafe { write_to_offset_unchecked(self.slice, 1, [new]) };
}
}