123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- use byteorder::{ByteOrder, NetworkEndian};
- use super::{Error, IpProtocol, Result};
- /// A read/write wrapper around an IPSec Authentication Header packet buffer.
- #[derive(Debug, PartialEq, Eq)]
- #[cfg_attr(feature = "defmt", derive(defmt::Format))]
- pub struct Packet<T: AsRef<[u8]>> {
- buffer: T,
- }
- mod field {
- use crate::wire::field::Field;
- pub const NEXT_HEADER: usize = 0;
- pub const PAYLOAD_LEN: usize = 1;
- pub const RESERVED: Field = 2..4;
- pub const SPI: Field = 4..8;
- pub const SEQUENCE_NUMBER: Field = 8..16;
- }
- impl<T: AsRef<[u8]>> Packet<T> {
- /// Imbue a raw octet buffer with IPsec Authentication Header packet structure.
- pub const fn new_unchecked(buffer: T) -> Packet<T> {
- Packet { buffer }
- }
- /// Shorthand for a combination of [new_unchecked] and [check_len].
- ///
- /// [new_unchecked]: #method.new_unchecked
- /// [check_len]: #method.check_len
- pub fn new_checked(buffer: T) -> Result<Packet<T>> {
- let packet = Self::new_unchecked(buffer);
- packet.check_len()?;
- Ok(packet)
- }
- /// Ensure that no accessor method will panic if called.
- /// Returns `Err(Error)` if the buffer is too short.
- /// Returns `Err(Error)` if the buffer is shorter than payload length
- ///
- /// The result of this check is invalidated by calling [set_payload_len].
- ///
- /// [set_payload_len]: #method.set_payload_len
- #[allow(clippy::if_same_then_else)]
- pub fn check_len(&self) -> Result<()> {
- let len = self.buffer.as_ref().len();
- if len < field::SEQUENCE_NUMBER.end {
- Err(Error)
- } else if len < self.header_len() {
- Err(Error)
- } else {
- Ok(())
- }
- }
- /// Consume the packet, returning the underlying buffer.
- pub fn into_inner(self) -> T {
- self.buffer
- }
- /// Return length of Authentication Header in octets
- pub fn header_len(&self) -> usize {
- (self.payload_len() as usize + 2) * 4
- }
- /// Return next header protocol type
- /// The value is taken from the list of IP protocol numbers.
- pub fn next_header(&self) -> IpProtocol {
- let data = self.buffer.as_ref();
- IpProtocol::from(data[field::NEXT_HEADER])
- }
- /// Return the length of this Authentication Header in 4-octet units, minus 2
- pub fn payload_len(&self) -> u8 {
- let data = self.buffer.as_ref();
- data[field::PAYLOAD_LEN]
- }
- /// Return the security parameters index
- pub fn security_parameters_index(&self) -> u32 {
- let field = &self.buffer.as_ref()[field::SPI];
- NetworkEndian::read_u32(field)
- }
- /// Return sequence number
- pub fn sequence_number(&self) -> u32 {
- let field = &self.buffer.as_ref()[field::SEQUENCE_NUMBER];
- NetworkEndian::read_u32(field)
- }
- }
- impl<'a, T: AsRef<[u8]> + ?Sized> Packet<&'a T> {
- /// Return a pointer to the integrity check value
- #[inline]
- pub fn integrity_check_value(&self) -> &'a [u8] {
- let range = field::SEQUENCE_NUMBER.end..self.header_len();
- let data = self.buffer.as_ref();
- &data[range]
- }
- }
- impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
- fn as_ref(&self) -> &[u8] {
- self.buffer.as_ref()
- }
- }
- impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
- /// Set next header protocol field
- fn set_next_header(&mut self, value: IpProtocol) {
- let data = self.buffer.as_mut();
- data[field::NEXT_HEADER] = value.into()
- }
- /// Set payload length field
- fn set_payload_len(&mut self, value: u8) {
- let data = self.buffer.as_mut();
- data[field::PAYLOAD_LEN] = value
- }
- /// Set security parameters index field
- fn set_security_parameters_index(&mut self, value: u32) {
- let data = self.buffer.as_mut();
- NetworkEndian::write_u32(&mut data[field::SPI], value)
- }
- /// Set sequence number
- fn set_sequence_number(&mut self, value: u32) {
- let data = self.buffer.as_mut();
- NetworkEndian::write_u32(&mut data[field::SEQUENCE_NUMBER], value)
- }
- /// Return a mutable pointer to the integrity check value.
- #[inline]
- pub fn integrity_check_value_mut(&mut self) -> &mut [u8] {
- let range = field::SEQUENCE_NUMBER.end..self.header_len();
- let data = self.buffer.as_mut();
- &mut data[range]
- }
- }
|