瀏覽代碼

Add basic esp

thegreathir 1 年之前
父節點
當前提交
516799e4eb
共有 4 個文件被更改,包括 119 次插入3 次删除
  1. 2 2
      Cargo.toml
  2. 1 1
      src/wire/ipsec_ah.rs
  3. 110 0
      src/wire/ipsec_esp.rs
  4. 6 0
      src/wire/mod.rs

+ 2 - 2
Cargo.toml

@@ -78,9 +78,9 @@ default = [
   "medium-ethernet", "medium-ip", "medium-ieee802154",
   "phy-raw_socket", "phy-tuntap_interface",
   "proto-ipv4", "proto-igmp", "proto-dhcpv4", "proto-ipv6", "proto-dns",
-  "proto-ipv4-fragmentation", "proto-sixlowpan-fragmentation",
+  "proto-ipv4-fragmentation", "proto-sixlowpan-fragmentation", "proto-ipsec-ah", "proto-ipsec-esp",
   "socket-raw", "socket-icmp", "socket-udp", "socket-tcp", "socket-dhcpv4", "socket-dns", "socket-mdns",
-  "packetmeta-id", "async", "proto-ipsec-ah"
+  "packetmeta-id", "async"
 ]
 
 # Private features

+ 1 - 1
src/wire/ipsec_ah.rs

@@ -171,7 +171,7 @@ pub struct Repr<'a> {
 }
 
 impl<'a> Repr<'a> {
-    /// Parse an IPSec Authentication Header packet and return a high-level representation,
+    /// Parse an IPSec Authentication Header packet and return a high-level representation.
     pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&'a T>) -> Result<Repr<'a>> {
         Ok(Repr {
             next_header: packet.next_header(),

+ 110 - 0
src/wire/ipsec_esp.rs

@@ -0,0 +1,110 @@
+use super::{Error, Result};
+use byteorder::{ByteOrder, NetworkEndian};
+
+/// A read/write wrapper around an IPSec Encapsulating Security Payload (ESP) 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 SPI: Field = 0..4;
+    pub const SEQUENCE_NUMBER: Field = 4..8;
+}
+
+impl<T: AsRef<[u8]>> Packet<T> {
+    /// Imbue a raw octet buffer with IPsec Encapsulating Security Payload 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.
+    pub fn check_len(&self) -> Result<()> {
+        let data = self.buffer.as_ref();
+        let len = data.len();
+        if len < field::SEQUENCE_NUMBER.end {
+            Err(Error)
+        } else {
+            Ok(())
+        }
+    }
+
+    /// Consume the packet, returning the underlying buffer.
+    pub fn into_inner(self) -> T {
+        self.buffer
+    }
+
+    /// 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<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 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)
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub struct Repr {
+    security_parameters_index: u32,
+    sequence_number: u32,
+}
+
+impl Repr {
+    /// Parse an IPSec Encapsulating Security Payload packet and return a high-level representation.
+    pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
+        Ok(Repr {
+            security_parameters_index: packet.security_parameters_index(),
+            sequence_number: packet.sequence_number(),
+        })
+    }
+
+    /// Return the length of a packet that will be emitted from this high-level representation.
+    pub const fn buffer_len(&self) -> usize {
+        field::SEQUENCE_NUMBER.end
+    }
+
+    /// Emit a high-level representation into an IPSec Encapsulating Security Payload.
+    pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
+        packet.set_security_parameters_index(self.security_parameters_index);
+        packet.set_sequence_number(self.sequence_number);
+    }
+}

+ 6 - 0
src/wire/mod.rs

@@ -130,6 +130,9 @@ mod udp;
 #[cfg(feature = "proto-ipsec-ah")]
 mod ipsec_ah;
 
+#[cfg(feature = "proto-ipsec-esp")]
+mod ipsec_esp;
+
 use core::fmt;
 
 use crate::phy::Medium;
@@ -278,6 +281,9 @@ pub use self::dns::{
 #[cfg(feature = "proto-ipsec-ah")]
 pub use self::ipsec_ah::{Packet as IPSecAuthHeaderPacket, Repr as IPSecAuthHeaderRepr};
 
+#[cfg(feature = "proto-ipsec-esp")]
+pub use self::ipsec_esp::{Packet as IPSecEspPacket, Repr as IPSecEspRepr};
+
 /// Parsing a packet failed.
 ///
 /// Either it is malformed, or it is not supported by smoltcp.