Skip to content
This repository has been archived by the owner on Oct 26, 2022. It is now read-only.

Add XFRM support #298

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ members = [
"netlink-packet-sock-diag",
"netlink-packet-netfilter",
"netlink-packet-wireguard",
"netlink-packet-xfrm",
"netlink-proto",
"ethtool",
"genetlink",
"rtnetlink",
"audit",
"mptcp-pm",
"xfrmnetlink",
]

# omit fuzz projects
Expand All @@ -31,10 +33,12 @@ default-members = [
"netlink-packet-sock-diag",
"netlink-packet-netfilter",
"netlink-packet-wireguard",
"netlink-packet-xfrm",
"netlink-proto",
"ethtool",
"genetlink",
"rtnetlink",
"audit",
"mptcp-pm",
"xfrmnetlink",
]
23 changes: 23 additions & 0 deletions netlink-packet-xfrm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "netlink-packet-xfrm"
version = "0.1.0"
authors = ["Scott Zuk <zooknotic@proton.me>"]
edition = "2018"
homepage = "https://github.com/zooknotic/netlink-packet-xfrm"
repository = "https://github.com/zooknotic/netlink-packet-xfrm"
keywords = ["netlink", "linux"]
license = "MIT"
readme = "../README.md"
description = "netlink xfrm packet types for IPsec"

[dependencies]
anyhow = "1.0.39"
byteorder = "1.4.2"
libc= "0.2.86"
netlink-packet-core = { version = "0.4.2", path = "../netlink-packet-core" }
netlink-packet-utils = { version = "0.5.1", path = "../netlink-packet-utils" }

[dev-dependencies]
lazy_static = "1.4.0"
netlink-proto = { path = "../netlink-proto", version = "0.10.0" }
netlink-sys = { path = "../netlink-sys", version = "0.8.3" }
25 changes: 25 additions & 0 deletions netlink-packet-xfrm/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

Distributions of all or part of the Software intended to be used by the
recipients as they would use the unmodified Software, containing modifications
that substantially alter, remove, or disable functionality of the Software,
outside of the documented configuration mechanisms provided by the Software,
shall be modified such that the Original Author's bug reporting email addresses
and urls are either replaced with the contact information of the parties
responsible for the changes, or removed entirely.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
60 changes: 60 additions & 0 deletions netlink-packet-xfrm/src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT

use std::net::{Ipv4Addr, Ipv6Addr};

use netlink_packet_utils::{buffer, traits::*, DecodeError};

pub const XFRM_ADDRESS_LEN: usize = 16;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct Address {
// Xfrm netlink API simply uses a 16 byte buffer for both IPv4 & IPv6
// addresses and unfortunately doesn't always pair it with a family type.
pub addr: [u8; XFRM_ADDRESS_LEN],
}

buffer!(AddressBuffer(XFRM_ADDRESS_LEN) {
addr: (slice, 0..XFRM_ADDRESS_LEN)
});

impl<T: AsRef<[u8]> + ?Sized> Parseable<AddressBuffer<&T>> for Address {
fn parse(buf: &AddressBuffer<&T>) -> Result<Self, DecodeError> {
let mut addr_payload: [u8; XFRM_ADDRESS_LEN] = [0; XFRM_ADDRESS_LEN];
addr_payload.clone_from_slice(&buf.addr());
Ok(Address { addr: addr_payload })
}
}

impl Emitable for Address {
fn buffer_len(&self) -> usize {
XFRM_ADDRESS_LEN
}

fn emit(&self, buffer: &mut [u8]) {
let mut buffer = AddressBuffer::new(buffer);
buffer.addr_mut().clone_from_slice(&self.addr[..]);
}
}

impl Address {
pub fn to_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(self.addr[0], self.addr[1], self.addr[2], self.addr[3])
}

pub fn to_ipv6(&self) -> Ipv6Addr {
Ipv6Addr::from(self.addr)
}

pub fn from_ipv4(ip: &Ipv4Addr) -> Address {
let mut addr_bytes: [u8; XFRM_ADDRESS_LEN] = [0; XFRM_ADDRESS_LEN];
addr_bytes[0] = ip.octets()[0];
addr_bytes[1] = ip.octets()[1];
addr_bytes[2] = ip.octets()[2];
addr_bytes[3] = ip.octets()[3];
Address { addr: addr_bytes }
}

pub fn from_ipv6(ip: &Ipv6Addr) -> Address {
Address { addr: ip.octets() }
}
}
62 changes: 62 additions & 0 deletions netlink-packet-xfrm/src/async_event_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT

use anyhow::Context;

use core::ops::Range;

use crate::{
Address, AddressBuffer, UserSaId, UserSaIdBuffer, XFRM_ADDRESS_LEN, XFRM_USER_SA_ID_LEN,
};

use netlink_packet_utils::{buffer, traits::*, DecodeError};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct AsyncEventId {
pub sa_id: UserSaId,
pub saddr: Address,
pub flags: u32,
pub reqid: u32,
}

const SA_ID_FIELD: Range<usize> = 0..XFRM_USER_SA_ID_LEN;
const SADDR_FIELD: Range<usize> = SA_ID_FIELD.end..(SA_ID_FIELD.end + XFRM_ADDRESS_LEN);
const FLAGS_FIELD: Range<usize> = SADDR_FIELD.end..(SADDR_FIELD.end + 4);
const REQID_FIELD: Range<usize> = FLAGS_FIELD.end..(FLAGS_FIELD.end + 4);

pub const XFRM_ASYNC_EVENT_ID_LEN: usize = (REQID_FIELD.end + 7) & !7; // 48

buffer!(AsyncEventIdBuffer(XFRM_ASYNC_EVENT_ID_LEN) {
sa_id: (slice, SA_ID_FIELD),
saddr: (slice, SADDR_FIELD),
flags: (u32, FLAGS_FIELD),
reqid: (u32, REQID_FIELD)
});

impl<T: AsRef<[u8]> + ?Sized> Parseable<AsyncEventIdBuffer<&T>> for AsyncEventId {
fn parse(buf: &AsyncEventIdBuffer<&T>) -> Result<Self, DecodeError> {
let sa_id =
UserSaId::parse(&UserSaIdBuffer::new(&buf.sa_id())).context("failed to parse sa_id")?;
let saddr =
Address::parse(&AddressBuffer::new(&buf.saddr())).context("failed to parse saddr")?;
Ok(AsyncEventId {
sa_id,
saddr,
flags: buf.flags(),
reqid: buf.reqid(),
})
}
}

impl Emitable for AsyncEventId {
fn buffer_len(&self) -> usize {
XFRM_ASYNC_EVENT_ID_LEN
}

fn emit(&self, buffer: &mut [u8]) {
let mut buffer = AsyncEventIdBuffer::new(buffer);
self.sa_id.emit(buffer.sa_id_mut());
self.saddr.emit(buffer.saddr_mut());
buffer.set_flags(self.flags);
buffer.set_reqid(self.reqid);
}
}
Loading