Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscelaneous fixes and features: Set bugfixes, Conntrack zone support, FIB support #55

Open
wants to merge 4 commits into
base: main
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
38 changes: 26 additions & 12 deletions nftnl/src/expr/ct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub enum Conntrack {
State,
Status,
Mark { set: bool },
Zone { set: bool },
}

impl Conntrack {
Expand All @@ -45,6 +46,9 @@ impl Conntrack {
Conntrack::State => libc::NFT_CT_STATE as u32,
Conntrack::Status => libc::NFT_CT_STATUS as u32,
Conntrack::Mark { .. } => libc::NFT_CT_MARK as u32,
// TODO: Update this once libc has definitions for NFT_CT_ZONE
// (https://github.com/rust-lang/libc/issues/3566)
Conntrack::Zone { .. } => 17 as u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Can you submit a PR to libc? We won't merge this with a hardcoded constant.

}
}
}
Expand All @@ -54,19 +58,23 @@ impl Expression for Conntrack {
unsafe {
let expr = try_alloc!(sys::nftnl_expr_alloc(b"ct\0" as *const _ as *const c_char));

if let Conntrack::Mark { set: true } = self {
sys::nftnl_expr_set_u32(
expr,
sys::NFTNL_EXPR_CT_SREG as u16,
libc::NFT_REG_1 as u32,
);
} else {
sys::nftnl_expr_set_u32(
expr,
sys::NFTNL_EXPR_CT_DREG as u16,
libc::NFT_REG_1 as u32,
);
match &self {
Conntrack::Mark { set: true } | Conntrack::Zone { set: true } => {
sys::nftnl_expr_set_u32(
expr,
sys::NFTNL_EXPR_CT_SREG as u16,
libc::NFT_REG_1 as u32,
);
}
_ => {
sys::nftnl_expr_set_u32(
expr,
sys::NFTNL_EXPR_CT_DREG as u16,
libc::NFT_REG_1 as u32,
);
}
}

sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_CT_KEY as u16, self.raw_key());

expr
Expand All @@ -88,4 +96,10 @@ macro_rules! nft_expr_ct {
(mark) => {
$crate::expr::Conntrack::Mark { set: false }
};
(zone set) => {
$crate::expr::Conntrack::Zone { set: true }
};
(zone) => {
$crate::expr::Conntrack::Zone { set: false }
};
}
121 changes: 121 additions & 0 deletions nftnl/src/expr/fib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use super::{Expression, Rule};
use nftnl_sys::{self as sys, libc};
use std::os::raw::c_char;
use std::str::FromStr;

#[non_exhaustive]
pub enum FibResult {
Oif,
OifName,
AddrType,
}

impl FromStr for FibResult {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_lowercase().as_str() {
"oif" => Ok(FibResult::Oif),
"oifname" => Ok(FibResult::OifName),
"type" => Ok(FibResult::AddrType),
_ => Err("Invalid FibResult variant"),
}
}
}

impl FibResult {
pub fn raw_result_type(&self) -> u32 {
use FibResult::*;

// From: linux/netfilter/nf_tables.h
match *self {
Oif => 1,
OifName => 2,
AddrType => 3,
}
}
}

#[non_exhaustive]
pub enum Fib {
SAddr { result: &'static str },
DAddr { result: &'static str },
Mark { result: &'static str },
Iif { result: &'static str },
Oif { result: &'static str },
Present { result: &'static str },
}

impl Fib {
pub fn flags(&self) -> u32 {
use Fib::*;

// From: linux/netfilter/nf_tables.h
match *self {
SAddr { .. } => 1 << 0,
DAddr { .. } => 1 << 1,
Mark { .. } => 1 << 2,
Iif { .. } => 1 << 3,
Oif { .. } => 1 << 4,
Present { .. } => 1 << 5,
}
}

pub fn result(&self) -> u32 {
use Fib::*;

let result: FibResult = match self {
SAddr { result }
| DAddr { result }
| Mark { result }
| Iif { result }
| Oif { result }
| Present { result } => result
.parse()
.expect("Unexpected fib result. Must be type, oif or oifname."),
};

result.raw_result_type()
}
}

impl Expression for Fib {
fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
unsafe {
let expr = try_alloc!(sys::nftnl_expr_alloc(b"fib\0" as *const _ as *const c_char));

sys::nftnl_expr_set_u32(
expr,
sys::NFTNL_EXPR_FIB_DREG as u16,
libc::NFT_REG_1 as u32,
);

sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_FIB_RESULT as u16, self.result());
sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_FIB_FLAGS as u16, self.flags());

expr
}
}
}

#[macro_export]
macro_rules! nft_expr_fib {
(saddr $result:expr) => {
$crate::expr::Fib::SAddr { result: $result }
};
(daddr $result:expr) => {
$crate::expr::Fib::DAddr { result: $result }
};
(mark $result:expr) => {
$crate::expr::Fib::Mark { result: $result }
};
(iif $result:expr) => {
$crate::expr::Fib::Iif { result: $result }
};
(oif $result:expr) => {
$crate::expr::Fib::Oif { result: $result }
};
(present $result:expr) => {
$crate::expr::Fib::Present { result: $result }
};
}
6 changes: 6 additions & 0 deletions nftnl/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub use self::payload::*;
mod verdict;
pub use self::verdict::*;

mod fib;
pub use self::fib::*;

#[macro_export(local_inner_macros)]
macro_rules! nft_expr {
(bitwise mask $mask:expr,xor $xor:expr) => {
Expand Down Expand Up @@ -104,4 +107,7 @@ macro_rules! nft_expr {
(immediate $expr:ident $value:expr) => {
nft_expr_immediate!($expr $value)
};
(fib $expr:ident $result:expr) => {
nft_expr_fib!($expr $result)
};
}
14 changes: 7 additions & 7 deletions nftnl/src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ macro_rules! nft_set {
nft_set!($name, $id, $table, $family)
};
($name:expr, $id:expr, $table:expr, $family:expr; [ $($value:expr,)* ]) => {{
let mut set = nft_set!($name, $id, $table, $family).expect("Set allocation failed");
let mut set = nft_set!($name, $id, $table, $family);
$(
set.add($value).expect(stringify!(Unable to add $value to set $name));
set.add($value);
)*
set
}};
Expand All @@ -32,6 +32,11 @@ pub struct Set<'a, K> {
_marker: ::std::marker::PhantomData<K>,
}

// Safety: It should be safe to pass this around and
// *read* from it from multiple threads
unsafe impl<'a, K> Send for Set<'a, K> where K: Send + Sync {}
unsafe impl<'a, K> Sync for Set<'a, K> where K: Send + Sync {}

impl<'a, K> Set<'a, K> {
pub fn new(name: &CStr, id: u32, table: &'a Table, family: ProtoFamily) -> Self
where
Expand All @@ -45,11 +50,6 @@ impl<'a, K> Set<'a, K> {
sys::nftnl_set_set_str(set, sys::NFTNL_SET_NAME as u16, name.as_ptr());
sys::nftnl_set_set_u32(set, sys::NFTNL_SET_ID as u16, id);

sys::nftnl_set_set_u32(
set,
sys::NFTNL_SET_FLAGS as u16,
(libc::NFT_SET_ANONYMOUS | libc::NFT_SET_CONSTANT) as u32,
);
sys::nftnl_set_set_u32(set, sys::NFTNL_SET_KEY_TYPE as u16, K::TYPE);
sys::nftnl_set_set_u32(set, sys::NFTNL_SET_KEY_LEN as u16, K::LEN);

Expand Down