pub mod address_filter;
pub use address_filter::*;
pub mod alg;
pub use alg::*;
pub mod alg_aead;
pub use alg_aead::*;
pub mod alg_auth;
pub use alg_auth::*;
pub mod encap_tmpl;
pub use encap_tmpl::*;
pub mod mark;
pub use mark::*;
pub mod replay;
pub use replay::*;
pub mod replay_esn;
pub use replay_esn::*;
#[allow(clippy::len_without_is_empty)]
pub mod security_ctx;
pub use security_ctx::*;
pub mod user_kmaddress;
pub use user_kmaddress::*;
pub mod user_migrate;
pub use user_migrate::*;
pub mod user_offload;
pub use user_offload::*;
pub mod user_template;
pub use user_template::*;
use anyhow::Context;
use byteorder::{ByteOrder, NativeEndian};
use std::mem::size_of;
use crate::{
constants::*, Address, AddressBuffer, Lifetime, LifetimeBuffer,
UserPolicyInfo, UserPolicyInfoBuffer, UserPolicyType, UserPolicyTypeBuffer,
UserSaInfo, UserSaInfoBuffer,
};
use netlink_packet_utils::{
nla::{DefaultNla, Nla, NlaBuffer},
parsers::*,
traits::*,
DecodeError,
};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum XfrmAttrs {
AddressFilter(address_filter::AddressFilter),
AuthenticationAlg(Alg),
AuthenticationAlgTrunc(AlgAuth),
CareOfAddr(Address),
CompressionAlg(Alg),
EncapsulationTemplate(EncapTmpl),
EncryptionAlg(Alg),
EncryptionAlgAead(AlgAead),
EventTimeThreshold(u32),
ExtraFlags(u32),
IfId(u32),
KmAddress(UserKmAddress),
LastUsed(u64),
LifetimeBytes(Lifetime), MappingTimeThreshold(u32),
Mark(mark::Mark),
MarkMask(u32),
MarkVal(u32),
Migrate(UserMigrate),
OffloadDevice(UserOffloadDev),
Pad(),
PolicyInfo(UserPolicyInfo),
PolicyType(UserPolicyType),
Proto(u8),
ReplayState(Replay), ReplayStateEsn(ReplayEsn), ReplayThreshold(u32), SaInfo(UserSaInfo),
SecurityContext(SecurityCtx),
SrcAddr(Address),
Template(Vec<UserTemplate>),
TfcPadding(u32),
Unspec(Vec<u8>),
Other(DefaultNla),
}
impl Nla for XfrmAttrs {
#[rustfmt::skip]
fn value_len(&self) -> usize {
use self::XfrmAttrs::*;
match *self {
AddressFilter(ref v) => v.buffer_len(),
AuthenticationAlg(ref v) => v.buffer_len(),
AuthenticationAlgTrunc(ref v) => v.buffer_len(),
CareOfAddr(ref v) => v.buffer_len(),
CompressionAlg(ref v) => v.buffer_len(),
EncapsulationTemplate(ref v) => v.buffer_len(),
EncryptionAlg(ref v) => v.buffer_len(),
EncryptionAlgAead(ref v) => v.buffer_len(),
EventTimeThreshold(_) => size_of::<u32>(),
ExtraFlags(_) => size_of::<u32>(),
IfId(_) => size_of::<u32>(),
KmAddress(ref v) => v.buffer_len(),
LastUsed(_) => size_of::<u64>(),
LifetimeBytes(ref v) => v.buffer_len(),
MappingTimeThreshold(_) => size_of::<u32>(),
Mark(ref v) => v.buffer_len(),
MarkMask(_) => size_of::<u32>(),
MarkVal(_) => size_of::<u32>(),
Migrate(ref v) => v.buffer_len(),
OffloadDevice(ref v) => v.buffer_len(),
Pad() => 0,
PolicyInfo(ref v) => v.buffer_len(),
PolicyType(ref v) => v.buffer_len(),
Proto(_) => size_of::<u8>(),
ReplayState(ref v) => v.buffer_len(),
ReplayStateEsn(ref v) => v.buffer_len(),
ReplayThreshold(_) => size_of::<u32>(),
SaInfo(ref v) => v.buffer_len(),
SecurityContext(ref v) => v.buffer_len(),
SrcAddr(ref v) => v.buffer_len(),
Template(ref v) => v.len() * XFRM_USER_TEMPLATE_LEN,
TfcPadding(_) => size_of::<u32>(),
Unspec(ref bytes) => bytes.len(),
Other(ref attr) => attr.value_len(),
}
}
fn emit_value(&self, buffer: &mut [u8]) {
use self::XfrmAttrs::*;
match *self {
AddressFilter(ref v) => v.emit(buffer),
AuthenticationAlg(ref v) => v.emit(buffer),
AuthenticationAlgTrunc(ref v) => v.emit(buffer),
CareOfAddr(ref v) => v.emit(buffer),
CompressionAlg(ref v) => v.emit(buffer),
EncapsulationTemplate(ref v) => v.emit(buffer),
EncryptionAlg(ref v) => v.emit(buffer),
EncryptionAlgAead(ref v) => v.emit(buffer),
EventTimeThreshold(ref v) => NativeEndian::write_u32(buffer, *v),
ExtraFlags(ref v) => NativeEndian::write_u32(buffer, *v),
IfId(ref v) => NativeEndian::write_u32(buffer, *v),
KmAddress(ref v) => v.emit(buffer),
LastUsed(ref v) => NativeEndian::write_u64(buffer, *v),
LifetimeBytes(ref v) => v.emit(buffer),
MappingTimeThreshold(ref v) => NativeEndian::write_u32(buffer, *v),
Mark(ref v) => v.emit(buffer),
MarkMask(ref v) => NativeEndian::write_u32(buffer, *v),
MarkVal(ref v) => NativeEndian::write_u32(buffer, *v),
Migrate(ref v) => v.emit(buffer),
OffloadDevice(ref v) => v.emit(buffer),
Pad() =>
{}
PolicyInfo(ref v) => v.emit(buffer),
PolicyType(ref v) => v.emit(buffer),
Proto(ref v) => buffer[0] = *v,
ReplayState(ref v) => v.emit(buffer),
ReplayStateEsn(ref v) => v.emit(buffer),
ReplayThreshold(ref v) => NativeEndian::write_u32(buffer, *v),
SaInfo(ref v) => v.emit(buffer),
SecurityContext(ref v) => v.emit(buffer),
SrcAddr(ref v) => v.emit(buffer),
Template(ref v) => {
let mut it_tmpl = v.iter();
let mut it_buf =
buffer.chunks_exact_mut(XFRM_USER_TEMPLATE_LEN);
loop {
if let (Some(tmpl), Some(buf)) =
(it_tmpl.next(), it_buf.next())
{
tmpl.emit(buf);
} else {
break;
}
}
}
TfcPadding(ref v) => NativeEndian::write_u32(buffer, *v),
Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
Other(ref attr) => attr.emit_value(buffer),
}
}
fn kind(&self) -> u16 {
use self::XfrmAttrs::*;
match *self {
AddressFilter(_) => XFRMA_ADDRESS_FILTER,
AuthenticationAlg(_) => XFRMA_ALG_AUTH,
AuthenticationAlgTrunc(_) => XFRMA_ALG_AUTH_TRUNC,
CareOfAddr(_) => XFRMA_COADDR,
CompressionAlg(_) => XFRMA_ALG_COMP,
EncapsulationTemplate(_) => XFRMA_ENCAP,
EncryptionAlg(_) => XFRMA_ALG_CRYPT,
EncryptionAlgAead(_) => XFRMA_ALG_AEAD,
EventTimeThreshold(_) => XFRMA_ETIMER_THRESH,
ExtraFlags(_) => XFRMA_SA_EXTRA_FLAGS,
IfId(_) => XFRMA_IF_ID,
KmAddress(_) => XFRMA_KMADDRESS,
LastUsed(_) => XFRMA_LASTUSED,
LifetimeBytes(_) => XFRMA_LTIME_VAL,
MappingTimeThreshold(_) => XFRMA_MTIMER_THRESH,
Mark(_) => XFRMA_MARK,
MarkMask(_) => XFRMA_SET_MARK_MASK,
MarkVal(_) => XFRMA_SET_MARK,
Migrate(_) => XFRMA_MIGRATE,
OffloadDevice(_) => XFRMA_OFFLOAD_DEV,
Pad() => XFRMA_PAD,
PolicyInfo(_) => XFRMA_POLICY,
PolicyType(_) => XFRMA_POLICY_TYPE,
Proto(_) => XFRMA_PROTO,
ReplayState(_) => XFRMA_REPLAY_VAL,
ReplayStateEsn(_) => XFRMA_REPLAY_ESN_VAL,
ReplayThreshold(_) => XFRMA_REPLAY_THRESH,
SaInfo(_) => XFRMA_SA,
SecurityContext(_) => XFRMA_SEC_CTX,
SrcAddr(_) => XFRMA_SRCADDR,
Template(_) => XFRMA_TMPL,
TfcPadding(_) => XFRMA_TFCPAD,
Unspec(_) => XFRMA_UNSPEC,
Other(ref nla) => nla.kind(),
}
}
}
impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for XfrmAttrs {
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
use self::XfrmAttrs::*;
let payload = buf.value();
Ok(match buf.kind() {
XFRMA_ADDRESS_FILTER => AddressFilter(
address_filter::AddressFilter::parse(
&AddressFilterBuffer::new(payload),
)
.context("invalid XFRMA_ADDRESS_FILTER")?,
),
XFRMA_ALG_AUTH => AuthenticationAlg(
Alg::parse(&AlgBuffer::new(payload))
.context("invalid XFRMA_ALG_AUTH")?,
),
XFRMA_ALG_AUTH_TRUNC => AuthenticationAlgTrunc(
AlgAuth::parse(&AlgAuthBuffer::new(payload))
.context("invalid XFRMA_ALG_AUTH_TRUNC")?,
),
XFRMA_COADDR => CareOfAddr(
Address::parse(&AddressBuffer::new(payload))
.context("invalid XFRMA_COADDR")?,
),
XFRMA_ALG_COMP => CompressionAlg(
Alg::parse(&AlgBuffer::new(payload))
.context("invalid XFRMA_ALG_COMP")?,
),
XFRMA_ENCAP => EncapsulationTemplate(
EncapTmpl::parse(&EncapTmplBuffer::new(payload))
.context("invalid XFRMA_ENCAP")?,
),
XFRMA_ALG_CRYPT => EncryptionAlg(
Alg::parse(&AlgBuffer::new(payload))
.context("invalid XFRMA_ALG_CRYPT")?,
),
XFRMA_ALG_AEAD => EncryptionAlgAead(
AlgAead::parse(&AlgAeadBuffer::new(payload))
.context("invalid XFRMA_ALG_AEAD")?,
),
XFRMA_ETIMER_THRESH => EventTimeThreshold(
parse_u32(payload).context("invalid XFRMA_ETIMER_THRESH")?,
),
XFRMA_SA_EXTRA_FLAGS => ExtraFlags(
parse_u32(payload).context("invalid XFRMA_SA_EXTRA_FLAGS")?,
),
XFRMA_IF_ID => {
IfId(parse_u32(payload).context("invalid XFRMA_IF_ID")?)
}
XFRMA_KMADDRESS => KmAddress(
UserKmAddress::parse(&UserKmAddressBuffer::new(payload))
.context("invalid XFRMA_KMADDRESS")?,
),
XFRMA_LASTUSED => {
LastUsed(parse_u64(payload).context("invalid XFRMA_LASTUSED")?)
}
XFRMA_LTIME_VAL => LifetimeBytes(
Lifetime::parse(&LifetimeBuffer::new(payload))
.context("invalid XFRMA_LTIME_VAL")?,
),
XFRMA_MTIMER_THRESH => MappingTimeThreshold(
parse_u32(payload).context("invalid XFRMA_MTIMER_THRESH")?,
),
XFRMA_MARK => Mark(
mark::Mark::parse(&MarkBuffer::new(payload))
.context("invalid XFRMA_MARK")?,
),
XFRMA_SET_MARK_MASK => MarkMask(
parse_u32(payload).context("invalid XFRMA_SET_MARK_MASK")?,
),
XFRMA_SET_MARK => {
MarkVal(parse_u32(payload).context("invalid XFRMA_SET_MARK")?)
}
XFRMA_MIGRATE => Migrate(
UserMigrate::parse(&UserMigrateBuffer::new(payload))
.context("invalid XFRMA_MIGRATE")?,
),
XFRMA_OFFLOAD_DEV => OffloadDevice(
UserOffloadDev::parse(&UserOffloadDevBuffer::new(payload))
.context("invalid XFRMA_OFFLOAD_DEV")?,
),
XFRMA_PAD => Pad(),
XFRMA_POLICY => PolicyInfo(
UserPolicyInfo::parse(&UserPolicyInfoBuffer::new(payload))
.context("invalid XFRMA_POLICY")?,
),
XFRMA_POLICY_TYPE => PolicyType(
UserPolicyType::parse(&UserPolicyTypeBuffer::new(payload))
.context("invalid XFRMA_POLICY_TYPE")?,
),
XFRMA_PROTO => {
Proto(parse_u8(payload).context("invalid XFRMA_PROTO")?)
}
XFRMA_REPLAY_VAL => ReplayState(
Replay::parse(&ReplayBuffer::new(payload))
.context("invalid XFRMA_REPLAY_VAL")?,
),
XFRMA_REPLAY_ESN_VAL => ReplayStateEsn(
ReplayEsn::parse(&ReplayEsnBuffer::new(payload))
.context("invalid XFRMA_REPLAY_ESN_VAL")?,
),
XFRMA_REPLAY_THRESH => ReplayThreshold(
parse_u32(payload).context("invalid XFRMA_REPLAY_THRESH")?,
),
XFRMA_SA => SaInfo(
UserSaInfo::parse(&UserSaInfoBuffer::new(payload))
.context("invalid XFRMA_SA")?,
),
XFRMA_SEC_CTX => SecurityContext(
SecurityCtx::parse(&SecurityCtxBuffer::new(payload))
.context("invalid XFRMA_SEC_CTX")?,
),
XFRMA_SRCADDR => SrcAddr(
Address::parse(&AddressBuffer::new(payload))
.context("invalid XFRMA_COADDR")?,
),
XFRMA_TMPL => {
let mut tmpls: Vec<UserTemplate> = vec![];
let it = payload.chunks_exact(XFRM_USER_TEMPLATE_LEN);
for t in it {
let tmpl =
UserTemplate::parse(&UserTemplateBuffer::new(&t))
.context("invalid XFRMA_TMPL")?;
tmpls.push(tmpl);
}
Template(tmpls)
}
XFRMA_TFCPAD => {
TfcPadding(parse_u32(payload).context("invalid XFRMA_TFCPAD")?)
}
XFRMA_UNSPEC => Unspec(payload.to_vec()),
kind => Other(
DefaultNla::parse(buf)
.context(format!("unknown NLA type {kind}"))?,
),
})
}
}