diff options
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 280 |
1 files changed, 7 insertions, 273 deletions
diff --git a/src/parser.rs b/src/parser.rs index c402dae..6ea34c1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,167 +1,21 @@ use std::{ - convert::TryFrom, fmt::{Debug, DebugStruct}, mem::{size_of, transmute}, - string::FromUtf8Error, }; -use thiserror::Error; - use crate::{ - nlmsg::{AttributeDecoder, NetlinkType, NfNetlinkAttribute, NfNetlinkDeserializable}, + error::DecodeError, + nlmsg::{ + get_operation_from_nlmsghdr_type, get_subsystem_from_nlmsghdr_type, pad_netlink_object, + pad_netlink_object_with_variable_size, AttributeDecoder, NetlinkType, NfNetlinkAttribute, + }, sys::{ nfgenmsg, nlattr, nlmsgerr, nlmsghdr, NFNETLINK_V0, NFNL_MSG_BATCH_BEGIN, - NFNL_MSG_BATCH_END, NFNL_SUBSYS_NFTABLES, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_ALIGNTO, - NLMSG_DONE, NLMSG_ERROR, NLMSG_MIN_TYPE, NLMSG_NOOP, NLM_F_DUMP_INTR, + NFNL_MSG_BATCH_END, NFNL_SUBSYS_NFTABLES, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, + NLMSG_ERROR, NLMSG_MIN_TYPE, NLMSG_NOOP, NLM_F_DUMP_INTR, }, - ProtocolFamily, }; -#[derive(Error, Debug)] -pub enum DecodeError { - #[error("The buffer is too small to hold a valid message")] - BufTooSmall, - - #[error("The message is too small")] - NlMsgTooSmall, - - #[error("The message holds unexpected data")] - InvalidDataSize, - - #[error("Missing information in the chain to create a rule")] - MissingChainInformationError, - - #[error("The length of the arguments are not compatible with each other")] - IncompatibleLength, - - #[error("Invalid subsystem, expected NFTABLES")] - InvalidSubsystem(u8), - - #[error("Invalid version, expected NFNETLINK_V0")] - InvalidVersion(u8), - - #[error("Invalid port ID")] - InvalidPortId(u32), - - #[error("Invalid sequence number")] - InvalidSeq(u32), - - #[error("The generation number was bumped in the kernel while the operation was running, interrupting it")] - ConcurrentGenerationUpdate, - - #[error("Unsupported message type")] - UnsupportedType(u16), - - #[error("Invalid attribute type")] - InvalidAttributeType, - - #[error("Invalid type for a chain")] - UnknownChainType, - - #[error("Invalid policy for a chain")] - UnknownChainPolicy, - - #[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")] - UnknownRegister(u32), - - #[error("Invalid type for a verdict expression")] - UnknownVerdictType(i32), - - #[error("Invalid type for a nat expression")] - UnknownNatType(i32), - - #[error("Invalid type for a payload expression")] - UnknownPayloadType(u32), - - #[error("Invalid type for a compare expression")] - UnknownCmpOp(u32), - - #[error("Invalid type for a conntrack key")] - UnknownConntrackKey(u32), - - #[error("Unsupported value for a link layer header field")] - UnknownLinkLayerHeaderField(u32, u32), - - #[error("Unsupported value for an IPv4 header field")] - UnknownIPv4HeaderField(u32, u32), - - #[error("Unsupported value for an IPv6 header field")] - UnknownIPv6HeaderField(u32, u32), - - #[error("Unsupported value for a TCP header field")] - UnknownTCPHeaderField(u32, u32), - - #[error("Unsupported value for an UDP header field")] - UnknownUDPHeaderField(u32, u32), - - #[error("Unsupported value for an ICMPv6 header field")] - UnknownICMPv6HeaderField(u32, u32), - - #[error("Missing the 'base' attribute to deserialize the payload object")] - PayloadMissingBase, - - #[error("Missing the 'offset' attribute to deserialize the payload object")] - PayloadMissingOffset, - - #[error("Missing the 'len' attribute to deserialize the payload object")] - PayloadMissingLen, - - #[error("The object does not contain a name for the expression being parsed")] - MissingExpressionName, - - #[error("Unsupported attribute type")] - UnsupportedAttributeType(u16), - - #[error("Unexpected message type")] - UnexpectedType(u16), - - #[error("The decoded String is not UTF8 compliant")] - StringDecodeFailure(#[from] FromUtf8Error), - - #[error("Invalid value for a protocol family")] - InvalidProtocolFamily(i32), - - #[error("A custom error occured")] - Custom(Box<dyn std::error::Error + 'static>), -} - -/// The largest nf_tables netlink message is the set element message, which contains the -/// NFTA_SET_ELEM_LIST_ELEMENTS attribute. This attribute is a nest that describes the set -/// elements. Given that the netlink attribute length (nla_len) is 16 bits, the largest message is -/// a bit larger than 64 KBytes. -pub fn nft_nlmsg_maxsize() -> u32 { - u32::from(::std::u16::MAX) + unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u32 -} - -#[inline] -pub const fn pad_netlink_object_with_variable_size(size: usize) -> usize { - // align on a 4 bytes boundary - (size + (NLMSG_ALIGNTO as usize - 1)) & !(NLMSG_ALIGNTO as usize - 1) -} - -#[inline] -pub const fn pad_netlink_object<T>() -> usize { - let size = size_of::<T>(); - pad_netlink_object_with_variable_size(size) -} - -pub fn get_subsystem_from_nlmsghdr_type(x: u16) -> u8 { - ((x & 0xff00) >> 8) as u8 -} - -pub fn get_operation_from_nlmsghdr_type(x: u16) -> u8 { - (x & 0x00ff) as u8 -} - pub fn get_nlmsghdr(buf: &[u8]) -> Result<nlmsghdr, DecodeError> { let size_of_hdr = size_of::<nlmsghdr>(); @@ -272,126 +126,6 @@ pub unsafe fn write_attribute<'a>( obj.write_payload(buf); } -impl NfNetlinkAttribute for u8 { - unsafe fn write_payload(&self, addr: *mut u8) { - *addr = *self; - } -} - -impl NfNetlinkDeserializable for u8 { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok((buf[0], &buf[1..])) - } -} - -impl NfNetlinkAttribute for u16 { - unsafe fn write_payload(&self, addr: *mut u8) { - *(addr as *mut Self) = self.to_be(); - } -} - -impl NfNetlinkDeserializable for u16 { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok((u16::from_be_bytes([buf[0], buf[1]]), &buf[2..])) - } -} - -impl NfNetlinkAttribute for i32 { - unsafe fn write_payload(&self, addr: *mut u8) { - *(addr as *mut Self) = self.to_be(); - } -} - -impl NfNetlinkDeserializable for i32 { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok(( - i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]), - &buf[4..], - )) - } -} - -impl NfNetlinkAttribute for u32 { - unsafe fn write_payload(&self, addr: *mut u8) { - *(addr as *mut Self) = self.to_be(); - } -} - -impl NfNetlinkDeserializable for u32 { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok(( - u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]), - &buf[4..], - )) - } -} - -impl NfNetlinkAttribute for u64 { - unsafe fn write_payload(&self, addr: *mut u8) { - *(addr as *mut Self) = self.to_be(); - } -} - -impl NfNetlinkDeserializable for u64 { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok(( - u64::from_be_bytes([ - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - ]), - &buf[8..], - )) - } -} - -impl NfNetlinkAttribute for String { - fn get_size(&self) -> usize { - self.len() - } - - unsafe fn write_payload(&self, addr: *mut u8) { - std::ptr::copy_nonoverlapping(self.as_bytes().as_ptr(), addr, self.len()); - } -} - -impl NfNetlinkDeserializable for String { - fn deserialize(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - // ignore the NULL byte terminator, if any - if buf.len() > 0 && buf[buf.len() - 1] == 0 { - buf = &buf[..buf.len() - 1]; - } - Ok((String::from_utf8(buf.to_vec())?, &[])) - } -} - -impl NfNetlinkAttribute for Vec<u8> { - fn get_size(&self) -> usize { - self.len() - } - - unsafe fn write_payload(&self, addr: *mut u8) { - std::ptr::copy_nonoverlapping(self.as_ptr(), addr, self.len()); - } -} - -impl NfNetlinkDeserializable for Vec<u8> { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - Ok((buf.to_vec(), &[])) - } -} - -impl NfNetlinkAttribute for ProtocolFamily { - unsafe fn write_payload(&self, addr: *mut u8) { - (*self as i32).write_payload(addr); - } -} - -impl NfNetlinkDeserializable for ProtocolFamily { - fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { - let (v, remaining_data) = i32::deserialize(buf)?; - Ok((Self::try_from(v)?, remaining_data)) - } -} - pub(crate) fn read_attributes<T: AttributeDecoder + Default>(buf: &[u8]) -> Result<T, DecodeError> { debug!( "Calling <{} as NfNetlinkDeserialize>::deserialize()", |