diff options
author | Simon THOBY <git@nightmared.fr> | 2022-12-03 00:19:39 +0100 |
---|---|---|
committer | Simon THOBY <git@nightmared.fr> | 2022-12-03 00:19:39 +0100 |
commit | 66de507d2d33c03203b996a0d1797543e84c4b3d (patch) | |
tree | b8f49965f221e09a82082eede8681e4405b99de3 /src | |
parent | 9ff02d4e40113ae10b6244a8a3d94c6e0bad5427 (diff) |
re-add the reject expression type
Diffstat (limited to 'src')
-rw-r--r-- | src/expr/mod.rs | 7 | ||||
-rw-r--r-- | src/expr/reject.rs | 161 | ||||
-rw-r--r-- | src/parser.rs | 6 |
3 files changed, 95 insertions, 79 deletions
diff --git a/src/expr/mod.rs b/src/expr/mod.rs index 6dfa6c7..4dc8ba1 100644 --- a/src/expr/mod.rs +++ b/src/expr/mod.rs @@ -62,10 +62,10 @@ pub use self::nat::*; mod payload; pub use self::payload::*; +*/ mod reject; -pub use self::reject::{IcmpCode, Reject}; -*/ +pub use self::reject::{IcmpCode, Reject, RejectType}; mod register; pub use self::register::Register; @@ -239,7 +239,8 @@ create_expr_variant!( [Immediate, Immediate], [Bitwise, Bitwise], [ExpressionRaw, ExpressionRaw], - [Meta, Meta] + [Meta, Meta], + [Reject, Reject] ); #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/src/expr/reject.rs b/src/expr/reject.rs index 34fbee5..e15f905 100644 --- a/src/expr/reject.rs +++ b/src/expr/reject.rs @@ -1,77 +1,72 @@ -use super::{DeserializationError, Expression, Rule}; -use crate::sys::{ - self, - libc::{self, c_char}, +use crate::{ + create_wrapper_type, + nlmsg::{NfNetlinkAttribute, NfNetlinkDeserializable}, + parser::DecodeError, + sys, }; -use crate::ProtoFamily; -/// A reject expression that defines the type of rejection message sent when discarding a packet. +use super::Expression; + +impl Expression for Reject { + fn get_name() -> &'static str { + "reject" + } +} + +// A reject expression that defines the type of rejection message sent when discarding a packet. +create_wrapper_type!( + inline: Reject, + [ + ( + get_type, + set_type, + with_type, + sys::NFTA_REJECT_TYPE, + reject_type, + RejectType + ), + ( + get_icmp_code, + set_icmp_code, + with_icmp_code, + sys::NFTA_REJECT_ICMP_CODE, + icmp_code, + IcmpCode + ) + ] +); + +/// An ICMP reject code. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub enum Reject { - /// Returns an ICMP unreachable packet. - Icmp(IcmpCode), - /// Rejects by sending a TCP RST packet. - TcpRst, +#[repr(u32)] +pub enum RejectType { + IcmpUnreach = sys::NFT_REJECT_ICMP_UNREACH, + TcpRst = sys::NFT_REJECT_TCP_RST, + IcmpxUnreach = sys::NFT_REJECT_ICMPX_UNREACH, } -impl Reject { - fn to_raw(&self, family: ProtoFamily) -> u32 { - use libc::*; - let value = match *self { - Self::Icmp(..) => match family { - ProtoFamily::Bridge | ProtoFamily::Inet => NFT_REJECT_ICMPX_UNREACH, - _ => NFT_REJECT_ICMP_UNREACH, +impl NfNetlinkDeserializable for RejectType { + fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (v, remaining_code) = u32::deserialize(buf)?; + Ok(( + match v { + sys::NFT_REJECT_ICMP_UNREACH => Self::IcmpUnreach, + sys::NFT_REJECT_TCP_RST => Self::TcpRst, + sys::NFT_REJECT_ICMPX_UNREACH => Self::IcmpxUnreach, + _ => return Err(DecodeError::UnknownRejectType(v)), }, - Self::TcpRst => NFT_REJECT_TCP_RST, - }; - value as u32 + remaining_code, + )) } } -impl Expression for Reject { - fn get_raw_name() -> *const libc::c_char { - b"reject\0" as *const _ as *const c_char +impl NfNetlinkAttribute for RejectType { + fn get_size(&self) -> usize { + (*self as u32).get_size() } - fn from_expr(expr: *const sys::nftnl_expr) -> Result<Self, DeserializationError> - where - Self: Sized, - { - unsafe { - if sys::nftnl_expr_get_u32(expr, sys::NFTNL_EXPR_REJECT_TYPE as u16) - == libc::NFT_REJECT_TCP_RST as u32 - { - Ok(Self::TcpRst) - } else { - Ok(Self::Icmp(IcmpCode::from_raw(sys::nftnl_expr_get_u8( - expr, - sys::NFTNL_EXPR_REJECT_CODE as u16, - ))?)) - } - } - } - - fn to_expr(&self, rule: &Rule) -> *mut sys::nftnl_expr { - let family = rule.get_chain().get_table().get_family(); - - unsafe { - let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name())); - - sys::nftnl_expr_set_u32( - expr, - sys::NFTNL_EXPR_REJECT_TYPE as u16, - self.to_raw(family), - ); - - let reject_code = match *self { - Reject::Icmp(code) => code as u8, - Reject::TcpRst => 0, - }; - - sys::nftnl_expr_set_u8(expr, sys::NFTNL_EXPR_REJECT_CODE as u16, reject_code); - - expr - } + unsafe fn write_payload(&self, addr: *mut u8) { + (*self as u32).write_payload(addr); } } @@ -79,20 +74,34 @@ impl Expression for Reject { #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] #[repr(u8)] pub enum IcmpCode { - NoRoute = libc::NFT_REJECT_ICMPX_NO_ROUTE as u8, - PortUnreach = libc::NFT_REJECT_ICMPX_PORT_UNREACH as u8, - HostUnreach = libc::NFT_REJECT_ICMPX_HOST_UNREACH as u8, - AdminProhibited = libc::NFT_REJECT_ICMPX_ADMIN_PROHIBITED as u8, + NoRoute = sys::NFT_REJECT_ICMPX_NO_ROUTE as u8, + PortUnreach = sys::NFT_REJECT_ICMPX_PORT_UNREACH as u8, + HostUnreach = sys::NFT_REJECT_ICMPX_HOST_UNREACH as u8, + AdminProhibited = sys::NFT_REJECT_ICMPX_ADMIN_PROHIBITED as u8, +} + +impl NfNetlinkDeserializable for IcmpCode { + fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (value, remaining_code) = u8::deserialize(buf)?; + Ok(( + match value as u32 { + sys::NFT_REJECT_ICMPX_NO_ROUTE => Self::NoRoute, + sys::NFT_REJECT_ICMPX_PORT_UNREACH => Self::PortUnreach, + sys::NFT_REJECT_ICMPX_HOST_UNREACH => Self::HostUnreach, + sys::NFT_REJECT_ICMPX_ADMIN_PROHIBITED => Self::AdminProhibited, + _ => return Err(DecodeError::UnknownIcmpCode(value)), + }, + remaining_code, + )) + } } -impl IcmpCode { - fn from_raw(code: u8) -> Result<Self, DeserializationError> { - match code as i32 { - libc::NFT_REJECT_ICMPX_NO_ROUTE => Ok(Self::NoRoute), - libc::NFT_REJECT_ICMPX_PORT_UNREACH => Ok(Self::PortUnreach), - libc::NFT_REJECT_ICMPX_HOST_UNREACH => Ok(Self::HostUnreach), - libc::NFT_REJECT_ICMPX_ADMIN_PROHIBITED => Ok(Self::AdminProhibited), - _ => Err(DeserializationError::InvalidValue), - } +impl NfNetlinkAttribute for IcmpCode { + fn get_size(&self) -> usize { + (*self as u8).get_size() + } + + unsafe fn write_payload(&self, addr: *mut u8) { + (*self as u8).write_payload(addr); } } diff --git a/src/parser.rs b/src/parser.rs index b7d0ac3..834874c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -68,6 +68,12 @@ pub enum DecodeError { #[error("Unknown type for a Meta expression")] UnknownMetaType(u32), + #[error("Unsupported value for an icmp reject type")] + UnknownRejectType(u32), + + #[error("Unsupported value for an icmp code in a reject expression")] + UnknownIcmpCode(u8), + #[error("Invalid value for a register")] UnknownRegisterValue, |