#![allow(missing_docs)]
use super::payload::PayloadKind;
pub const HEADER_LEN: usize = 28;
pub const IKE_VERSION: u8 = 0x20;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExchangeType {
IkeSaInit,
IkeAuth,
CreateChildSa,
Informational,
Other(u8),
}
impl ExchangeType {
pub fn from_u8(v: u8) -> Self {
match v {
34 => Self::IkeSaInit,
35 => Self::IkeAuth,
36 => Self::CreateChildSa,
37 => Self::Informational,
other => Self::Other(other),
}
}
pub fn as_u8(self) -> u8 {
match self {
Self::IkeSaInit => 34,
Self::IkeAuth => 35,
Self::CreateChildSa => 36,
Self::Informational => 37,
Self::Other(v) => v,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Flags(pub u8);
impl Flags {
pub const INITIATOR: u8 = 0b0000_1000;
pub const VERSION: u8 = 0b0001_0000;
pub const RESPONSE: u8 = 0b0010_0000;
pub fn is_initiator(self) -> bool {
self.0 & Self::INITIATOR != 0
}
pub fn is_response(self) -> bool {
self.0 & Self::RESPONSE != 0
}
pub fn higher_version(self) -> bool {
self.0 & Self::VERSION != 0
}
}
#[derive(Debug, Clone, Copy)]
pub struct Header {
pub initiator_spi: u64,
pub responder_spi: u64,
pub next_payload: PayloadKind,
pub version: u8,
pub exchange_type: ExchangeType,
pub flags: Flags,
pub message_id: u32,
pub length: u32,
}
impl Header {
pub fn parse(bytes: &[u8]) -> Result<Self, super::ParseError> {
if bytes.len() < HEADER_LEN {
return Err(super::ParseError::Truncated {
what: "ike header",
need: HEADER_LEN,
got: bytes.len(),
});
}
let initiator_spi = u64::from_be_bytes(bytes[0..8].try_into().unwrap());
let responder_spi = u64::from_be_bytes(bytes[8..16].try_into().unwrap());
let next_payload = PayloadKind::from_u8(bytes[16]);
let version = bytes[17];
let exchange_type = ExchangeType::from_u8(bytes[18]);
let flags = Flags(bytes[19]);
let message_id = u32::from_be_bytes(bytes[20..24].try_into().unwrap());
let length = u32::from_be_bytes(bytes[24..28].try_into().unwrap());
Ok(Self {
initiator_spi,
responder_spi,
next_payload,
version,
exchange_type,
flags,
message_id,
length,
})
}
pub fn write_into(&self, out: &mut [u8; HEADER_LEN]) {
out[0..8].copy_from_slice(&self.initiator_spi.to_be_bytes());
out[8..16].copy_from_slice(&self.responder_spi.to_be_bytes());
out[16] = self.next_payload.as_u8();
out[17] = self.version;
out[18] = self.exchange_type.as_u8();
out[19] = self.flags.0;
out[20..24].copy_from_slice(&self.message_id.to_be_bytes());
out[24..28].copy_from_slice(&self.length.to_be_bytes());
}
}