aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nftnl/src/expr/immediate.rs95
1 files changed, 66 insertions, 29 deletions
diff --git a/nftnl/src/expr/immediate.rs b/nftnl/src/expr/immediate.rs
index 0e89abc..c8885a3 100644
--- a/nftnl/src/expr/immediate.rs
+++ b/nftnl/src/expr/immediate.rs
@@ -42,14 +42,16 @@ macro_rules! nft_expr_immediate {
};
}
-/// A verdict expression. In the background actually an "Immediate" expression in nftnl terms,
-/// but here it's simplified to only represent a verdict.
+/// A verdict expression. In the background, this is usually an "Immediate" expression in nftnl
+/// terms, but here it is simplified to only represent a verdict.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Verdict {
/// Silently drop the packet.
Drop,
/// Accept the packet and let it pass.
Accept,
+ /// Reject the packet and return a message.
+ Reject,
Queue,
Continue,
Break,
@@ -63,19 +65,43 @@ pub enum Verdict {
}
impl Verdict {
- fn verdict_const(&self) -> i32 {
+ fn immediate_const(&self) -> Option<i32> {
match *self {
- Verdict::Drop => libc::NF_DROP,
- Verdict::Accept => libc::NF_ACCEPT,
- Verdict::Queue => libc::NF_QUEUE,
- Verdict::Continue => libc::NFT_CONTINUE,
- Verdict::Break => libc::NFT_BREAK,
- Verdict::Jump { .. } => libc::NFT_JUMP,
- Verdict::Goto { .. } => libc::NFT_GOTO,
- Verdict::Return => libc::NFT_RETURN,
+ Verdict::Drop => Some(libc::NF_DROP),
+ Verdict::Accept => Some(libc::NF_ACCEPT),
+ Verdict::Queue => Some(libc::NF_QUEUE),
+ Verdict::Continue => Some(libc::NFT_CONTINUE),
+ Verdict::Break => Some(libc::NFT_BREAK),
+ Verdict::Jump { .. } => Some(libc::NFT_JUMP),
+ Verdict::Goto { .. } => Some(libc::NFT_GOTO),
+ Verdict::Return => Some(libc::NFT_RETURN),
+ _ => None,
}
}
+ unsafe fn immediate_to_expr(&self, immediate_const: i32) -> *mut sys::nftnl_expr {
+ let expr = try_alloc!(sys::nftnl_expr_alloc(
+ b"immediate\0" as *const _ as *const c_char
+ ));
+
+ sys::nftnl_expr_set_u32(
+ expr,
+ sys::NFTNL_EXPR_IMM_DREG as u16,
+ libc::NFT_REG_VERDICT as u32,
+ );
+
+ if let Some(chain) = self.chain() {
+ sys::nftnl_expr_set_str(expr, sys::NFTNL_EXPR_IMM_CHAIN as u16, chain.as_ptr());
+ }
+ sys::nftnl_expr_set_u32(
+ expr,
+ sys::NFTNL_EXPR_IMM_VERDICT as u16,
+ immediate_const as u32,
+ );
+
+ expr
+ }
+
fn chain(&self) -> Option<&CStr> {
match *self {
Verdict::Jump { ref chain } => Some(chain.as_c_str()),
@@ -86,28 +112,36 @@ impl Verdict {
}
impl Expression for Verdict {
+
fn to_expr(&self) -> *mut sys::nftnl_expr {
- unsafe {
- let expr = try_alloc!(sys::nftnl_expr_alloc(
- b"immediate\0" as *const _ as *const c_char
- ));
+ if let Some(immediate_const) = self.immediate_const() {
+ return unsafe { self.immediate_to_expr(immediate_const) };
+ }
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_IMM_DREG as u16,
- libc::NFT_REG_VERDICT as u32,
- );
+ match *self {
+ Verdict::Reject => {
+ unsafe {
+ let expr = try_alloc!(sys::nftnl_expr_alloc(
+ b"reject\0" as *const _ as *const c_char
+ ));
- if let Some(chain) = self.chain() {
- sys::nftnl_expr_set_str(expr, sys::NFTNL_EXPR_IMM_CHAIN as u16, chain.as_ptr());
- }
- sys::nftnl_expr_set_u32(
- expr,
- sys::NFTNL_EXPR_IMM_VERDICT as u16,
- self.verdict_const() as u32,
- );
+ sys::nftnl_expr_set_u32(
+ expr,
+ sys::NFTNL_EXPR_REJECT_TYPE as u16,
+ libc::NFT_REJECT_ICMPX_UNREACH as u32,
+ );
- expr
+ // TODO: Allow setting the ICMP code
+ sys::nftnl_expr_set_u8(
+ expr,
+ sys::NFTNL_EXPR_REJECT_CODE as u16,
+ libc::NFT_REJECT_ICMPX_HOST_UNREACH as u8,
+ );
+
+ expr
+ }
+ }
+ _ => unreachable!("unsupported verdict"),
}
}
}
@@ -120,6 +154,9 @@ macro_rules! nft_expr_verdict {
(accept) => {
$crate::expr::Verdict::Accept
};
+ (reject) => {
+ $crate::expr::Verdict::Reject
+ };
(queue) => {
$crate::expr::Verdict::Queue
};