diff options
author | David Lönnhager <david.l@mullvad.net> | 2020-05-18 13:28:28 +0200 |
---|---|---|
committer | David Lönnhager <david.l@mullvad.net> | 2020-05-19 10:33:40 +0200 |
commit | e50e459d506f0f6e9e58e6d0298f1754e90aef98 (patch) | |
tree | 6fedb8ca0a9c271ddb7bb4312e0f5a46bda5e933 | |
parent | 39982629ee8c4bc129f3a80b844d9d3d9486d5d7 (diff) |
Add Verdict::Reject
-rw-r--r-- | nftnl/src/expr/immediate.rs | 95 |
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 }; |