From ac9a1b51e0c3c1ba6a179986caf0323f3ae3efd5 Mon Sep 17 00:00:00 2001 From: Johan Mazel Date: Fri, 2 Aug 2024 18:19:14 +0200 Subject: [PATCH 1/2] add IpAddrProtoPort --- .../container/ipaddr_proto_port_container.rs | 35 +++++++++++++------ pcap-rewrite/src/filters/dispatch_filter.rs | 20 +++++------ .../src/filters/fragmentation/convert_fn.rs | 6 ++-- .../fragmentation/fragmentation_filter.rs | 20 +++++------ pcap-rewrite/src/filters/key_parser_ipv4.rs | 27 +++++++++----- pcap-rewrite/src/filters/key_parser_ipv6.rs | 18 +++++++--- 6 files changed, 76 insertions(+), 50 deletions(-) diff --git a/pcap-rewrite/src/container/ipaddr_proto_port_container.rs b/pcap-rewrite/src/container/ipaddr_proto_port_container.rs index e9798c0..127b24c 100644 --- a/pcap-rewrite/src/container/ipaddr_proto_port_container.rs +++ b/pcap-rewrite/src/container/ipaddr_proto_port_container.rs @@ -1,7 +1,6 @@ use std::collections::HashSet; use std::error::Error; use std::fs::File; -use std::iter::FromIterator; use std::net::IpAddr; use std::path::Path; use std::str::FromStr; @@ -9,12 +8,29 @@ use std::str::FromStr; use csv::ReaderBuilder; use pnet_packet::ip::IpNextHeaderProtocol; +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct IpAddrProtoPort { + ipaddr: IpAddr, + proto: IpNextHeaderProtocol, + port: u16, +} + +impl IpAddrProtoPort { + pub fn new(ipaddr: IpAddr, proto: IpNextHeaderProtocol, port: u16) -> IpAddrProtoPort { + IpAddrProtoPort { + ipaddr, + proto, + port, + } + } +} + pub struct IpAddrProtoPortC { - s: HashSet<(IpAddr, IpNextHeaderProtocol, u16)>, + s: HashSet, } impl IpAddrProtoPortC { - pub fn new(s: HashSet<(IpAddr, IpNextHeaderProtocol, u16)>) -> IpAddrProtoPortC { + pub fn new(s: HashSet) -> IpAddrProtoPortC { IpAddrProtoPortC { s } } @@ -22,7 +38,7 @@ impl IpAddrProtoPortC { let file = File::open(ip_file_path)?; let mut rdr = ReaderBuilder::new().has_headers(false).from_reader(file); - let ipaddr_proto_port_v = rdr + let hs = rdr .records() .map(|l| { let record = l?; @@ -45,11 +61,9 @@ impl IpAddrProtoPortC { .ok_or_else(|| "Missing port value in dispatch filter key file".to_string())?; let port = port_s.parse()?; - Ok((ipaddr, protocol, port)) + Ok(IpAddrProtoPort::new(ipaddr, protocol, port)) }) - .collect::, Box>>()?; - - let hs = HashSet::from_iter(ipaddr_proto_port_v.iter().cloned()); + .collect::, Box>>()?; Ok(IpAddrProtoPortC::new(hs)) } @@ -62,8 +76,7 @@ impl IpAddrProtoPortC { // self.s.len() // } - pub fn contains(&self, ipaddr: &IpAddr, proto: &IpNextHeaderProtocol, port: u16) -> bool { - let t = (*ipaddr, *proto, port); - self.s.contains(&t) + pub fn contains(&self, ipaddr_proto_port: &IpAddrProtoPort) -> bool { + self.s.contains(ipaddr_proto_port) } } diff --git a/pcap-rewrite/src/filters/dispatch_filter.rs b/pcap-rewrite/src/filters/dispatch_filter.rs index 8f74eaa..66709f4 100644 --- a/pcap-rewrite/src/filters/dispatch_filter.rs +++ b/pcap-rewrite/src/filters/dispatch_filter.rs @@ -6,12 +6,11 @@ use std::path::Path; use libpcap_tools::{Error, FiveTuple, ParseContext}; use pcap_parser::data::PacketData; use pnet_packet::ethernet::{EtherType, EtherTypes}; -use pnet_packet::ip::IpNextHeaderProtocol; use pnet_packet::PrimitiveValues; use crate::container::five_tuple_container::FiveTupleC; use crate::container::ipaddr_container::IpAddrC; -use crate::container::ipaddr_proto_port_container::IpAddrProtoPortC; +use crate::container::ipaddr_proto_port_container::{IpAddrProtoPort, IpAddrProtoPortC}; use crate::filters::filter::{FResult, Filter, Verdict}; use crate::filters::filter_utils; use crate::filters::filtering_action::FilteringAction; @@ -180,15 +179,14 @@ impl DispatchFilterBuilder { IpAddrProtoPortC::of_file_path(Path::new(key_file_path)) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?; - let keep: KeepFn = - match filtering_action { - FilteringAction::Keep => { - Box::new(|c, tuple| Ok(c.contains(&tuple.0, &tuple.1, tuple.2))) - } - FilteringAction::Drop => { - Box::new(|c, tuple| Ok(!c.contains(&tuple.0, &tuple.1, tuple.2))) - } - }; + let keep: KeepFn = match filtering_action { + FilteringAction::Keep => { + Box::new(|c, ipaddr_proto_port| Ok(c.contains(ipaddr_proto_port))) + } + FilteringAction::Drop => { + Box::new(|c, ipaddr_proto_port| Ok(!c.contains(ipaddr_proto_port))) + } + }; Ok(Box::new(DispatchFilter::new( ipaddr_proto_port_container, diff --git a/pcap-rewrite/src/filters/fragmentation/convert_fn.rs b/pcap-rewrite/src/filters/fragmentation/convert_fn.rs index d6e9852..bc6aa75 100644 --- a/pcap-rewrite/src/filters/fragmentation/convert_fn.rs +++ b/pcap-rewrite/src/filters/fragmentation/convert_fn.rs @@ -7,7 +7,7 @@ use libpcap_tools::FiveTuple; use crate::container::five_tuple_container::FiveTupleC; use crate::container::ipaddr_container::IpAddrC; -use crate::container::ipaddr_proto_port_container::IpAddrProtoPortC; +use crate::container::ipaddr_proto_port_container::{IpAddrProtoPort, IpAddrProtoPortC}; use crate::container::two_tuple_proto_ipid_container::TwoTupleProtoIpidC; use crate::filters::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; @@ -51,7 +51,7 @@ pub fn convert_data_hs_to_src_ipaddr_proto_dst_port_container( .iter() .filter_map(|t| t.get_five_tuple_option()) .map(|five_tuple| { - ( + IpAddrProtoPort::new( five_tuple.src, IpNextHeaderProtocol::new(five_tuple.proto), five_tuple.dst_port, @@ -61,7 +61,7 @@ pub fn convert_data_hs_to_src_ipaddr_proto_dst_port_container( .iter() .filter_map(|t| t.get_five_tuple_option()) .map(|five_tuple| { - ( + IpAddrProtoPort::new( five_tuple.dst, IpNextHeaderProtocol::new(five_tuple.proto), five_tuple.src_port, diff --git a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs index de27fff..db6af80 100644 --- a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs +++ b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs @@ -5,13 +5,12 @@ use std::net::IpAddr; use log::warn; use pcap_parser::data::PacketData; use pnet_packet::ethernet::{EtherType, EtherTypes}; -use pnet_packet::ip::IpNextHeaderProtocol; use libpcap_tools::{Error, Packet, ParseContext}; use crate::container::five_tuple_container::FiveTupleC; use crate::container::ipaddr_container::IpAddrC; -use crate::container::ipaddr_proto_port_container::IpAddrProtoPortC; +use crate::container::ipaddr_proto_port_container::{IpAddrProtoPort, IpAddrProtoPortC}; use crate::container::two_tuple_proto_ipid_container::TwoTupleProtoIpidC; use crate::filters::filter::Filter; use crate::filters::filter::{FResult, Verdict}; @@ -319,15 +318,14 @@ impl FragmentationFilterBuilder { FilteringKey::SrcIpaddrProtoDstPort => { let ipaddr_proto_port_container = IpAddrProtoPortC::new(HashSet::new()); - let keep: KeepFn = - match filtering_action { - FilteringAction::Keep => { - |c, tuple| Ok(c.contains(&tuple.0, &tuple.1, tuple.2)) - } - FilteringAction::Drop => { - |c, tuple| Ok(!c.contains(&tuple.0, &tuple.1, tuple.2)) - } - }; + let keep: KeepFn = match filtering_action { + FilteringAction::Keep => { + |c: &IpAddrProtoPortC, ipaddr_proto_port| Ok(c.contains(ipaddr_proto_port)) + } + FilteringAction::Drop => { + |c, ipaddr_proto_port| Ok(!c.contains(ipaddr_proto_port)) + } + }; Ok(Box::new(FragmentationFilter::new( HashSet::new(), diff --git a/pcap-rewrite/src/filters/key_parser_ipv4.rs b/pcap-rewrite/src/filters/key_parser_ipv4.rs index b75842e..9445c05 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv4.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv4.rs @@ -1,7 +1,6 @@ use std::net::IpAddr; use log::warn; -use pnet_packet::ip::IpNextHeaderProtocol; use pnet_packet::ip::IpNextHeaderProtocols; use pnet_packet::ipv4::Ipv4Packet; use pnet_packet::tcp::TcpPacket; @@ -12,6 +11,7 @@ use libpcap_tools::{Error, FiveTuple, ParseContext}; use super::fragmentation::two_tuple_proto_ipid::TwoTupleProtoIpid; use super::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; +use crate::container::ipaddr_proto_port_container::IpAddrProtoPort; pub fn parse_src_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result { let ipv4 = Ipv4Packet::new(payload).ok_or_else(|| { @@ -35,10 +35,7 @@ pub fn parse_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result Result<(IpAddr, IpAddr), Error> { +pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result<(IpAddr, IpAddr), Error> { let ipv4_packet = Ipv4Packet::new(payload).ok_or_else(|| { warn!( "Expected Ipv4 packet but could not parse at index {}", @@ -54,7 +51,7 @@ pub fn parse_src_dst_ipaddr( pub fn parse_src_ipaddr_proto_dst_port( ctx: &ParseContext, payload: &[u8], -) -> Result<(IpAddr, IpNextHeaderProtocol, u16), Error> { +) -> Result { let ipv4_packet = Ipv4Packet::new(payload).ok_or_else(|| { warn!( "Expected Ipv4 packet but could not parse at index {}", @@ -71,7 +68,11 @@ pub fn parse_src_ipaddr_proto_dst_port( match TcpPacket::new(ipv4_payload) { Some(ref tcp) => { let dst_port = tcp.get_destination(); - Ok((src_ipaddr, IpNextHeaderProtocols::Tcp, dst_port)) + Ok(IpAddrProtoPort::new( + src_ipaddr, + IpNextHeaderProtocols::Tcp, + dst_port, + )) } None => { warn!( @@ -87,7 +88,11 @@ pub fn parse_src_ipaddr_proto_dst_port( IpNextHeaderProtocols::Udp => match UdpPacket::new(ipv4_packet.payload()) { Some(ref udp) => { let dst_port = udp.get_destination(); - Ok((src_ipaddr, IpNextHeaderProtocols::Udp, dst_port)) + Ok(IpAddrProtoPort::new( + src_ipaddr, + IpNextHeaderProtocols::Udp, + dst_port, + )) } None => { warn!( @@ -99,7 +104,11 @@ pub fn parse_src_ipaddr_proto_dst_port( )) } }, - _ => Ok((src_ipaddr, ipv4_packet.get_next_level_protocol(), 0)), + _ => Ok(IpAddrProtoPort::new( + src_ipaddr, + ipv4_packet.get_next_level_protocol(), + 0, + )), } } diff --git a/pcap-rewrite/src/filters/key_parser_ipv6.rs b/pcap-rewrite/src/filters/key_parser_ipv6.rs index c0864cd..3c8823c 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv6.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv6.rs @@ -1,12 +1,12 @@ use std::net::IpAddr; use log::warn; -use pnet_packet::ip::IpNextHeaderProtocol; use pnet_packet::ip::IpNextHeaderProtocols; use pnet_packet::ipv6::Ipv6Packet; use pnet_packet::tcp::TcpPacket; use pnet_packet::udp::UdpPacket; +use crate::container::ipaddr_proto_port_container::IpAddrProtoPort; use crate::filters::ipv6_utils; use libpcap_tools::{Error, FiveTuple, ParseContext}; @@ -51,7 +51,7 @@ pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result<(IpAdd pub fn parse_src_ipaddr_proto_dst_port( ctx: &ParseContext, payload: &[u8], -) -> Result<(IpAddr, IpNextHeaderProtocol, u16), Error> { +) -> Result { let ipv6_packet = Ipv6Packet::new(payload).ok_or_else(|| { warn!( "Expected Ipv6 packet but could not parse at index {}", @@ -69,7 +69,11 @@ pub fn parse_src_ipaddr_proto_dst_port( IpNextHeaderProtocols::Tcp => match TcpPacket::new(payload) { Some(ref tcp) => { let dst_port = tcp.get_destination(); - Ok((src_ipaddr, IpNextHeaderProtocols::Tcp, dst_port)) + Ok(IpAddrProtoPort::new( + src_ipaddr, + IpNextHeaderProtocols::Tcp, + dst_port, + )) } None => { warn!( @@ -84,7 +88,11 @@ pub fn parse_src_ipaddr_proto_dst_port( IpNextHeaderProtocols::Udp => match UdpPacket::new(payload) { Some(ref udp) => { let dst_port = udp.get_destination(); - Ok((src_ipaddr, IpNextHeaderProtocols::Udp, dst_port)) + Ok(IpAddrProtoPort::new( + src_ipaddr, + IpNextHeaderProtocols::Udp, + dst_port, + )) } None => { warn!( @@ -96,7 +104,7 @@ pub fn parse_src_ipaddr_proto_dst_port( )) } }, - _ => Ok((src_ipaddr, l4_proto, 0)), + _ => Ok(IpAddrProtoPort::new(src_ipaddr, l4_proto, 0)), } } From 72e6a1b5f8fcd80adb59f2b6181c9d2396a951c4 Mon Sep 17 00:00:00 2001 From: Johan Mazel Date: Fri, 2 Aug 2024 18:34:54 +0200 Subject: [PATCH 2/2] add IpAddrPair --- pcap-rewrite/src/filters/dispatch_filter.rs | 11 ++++++----- .../fragmentation/fragmentation_filter.rs | 18 +++++++++--------- pcap-rewrite/src/filters/ipaddr_pair.rs | 9 +++++++++ pcap-rewrite/src/filters/key_parser_ipv4.rs | 5 +++-- pcap-rewrite/src/filters/key_parser_ipv6.rs | 5 +++-- pcap-rewrite/src/filters/mod.rs | 1 + 6 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 pcap-rewrite/src/filters/ipaddr_pair.rs diff --git a/pcap-rewrite/src/filters/dispatch_filter.rs b/pcap-rewrite/src/filters/dispatch_filter.rs index 66709f4..9218b59 100644 --- a/pcap-rewrite/src/filters/dispatch_filter.rs +++ b/pcap-rewrite/src/filters/dispatch_filter.rs @@ -15,6 +15,7 @@ use crate::filters::filter::{FResult, Filter, Verdict}; use crate::filters::filter_utils; use crate::filters::filtering_action::FilteringAction; use crate::filters::filtering_key::FilteringKey; +use crate::filters::ipaddr_pair::IpAddrPair; use crate::filters::key_parser_ipv4; use crate::filters::key_parser_ipv6; @@ -158,12 +159,12 @@ impl DispatchFilterBuilder { let ipaddr_container = IpAddrC::of_file_path(Path::new(key_file_path)) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?; - let keep: KeepFn = match filtering_action { - FilteringAction::Keep => Box::new(|c, ipaddr_tuple| { - Ok(c.contains(&ipaddr_tuple.0) || c.contains(&ipaddr_tuple.1)) + let keep: KeepFn = match filtering_action { + FilteringAction::Keep => Box::new(|c, ipaddr_pair| { + Ok(c.contains(&ipaddr_pair.0) || c.contains(&ipaddr_pair.1)) }), - FilteringAction::Drop => Box::new(|c, ipaddr_tuple| { - Ok(!c.contains(&ipaddr_tuple.0) && !c.contains(&ipaddr_tuple.1)) + FilteringAction::Drop => Box::new(|c, ipaddr_pair| { + Ok(!c.contains(&ipaddr_pair.0) && !c.contains(&ipaddr_pair.1)) }), }; diff --git a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs index db6af80..af26ae2 100644 --- a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs +++ b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs @@ -17,11 +17,11 @@ use crate::filters::filter::{FResult, Verdict}; use crate::filters::filter_utils; use crate::filters::filtering_action::FilteringAction; use crate::filters::filtering_key::FilteringKey; -use crate::filters::key_parser_ipv4; -use crate::filters::key_parser_ipv6; - use crate::filters::fragmentation::fragmentation_test; use crate::filters::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; +use crate::filters::ipaddr_pair::IpAddrPair; +use crate::filters::key_parser_ipv4; +use crate::filters::key_parser_ipv6; use super::convert_fn; @@ -297,12 +297,12 @@ impl FragmentationFilterBuilder { FilteringKey::SrcDstIpaddr => { let ipaddr_container = IpAddrC::new(HashSet::new()); - let keep: KeepFn = match filtering_action { - FilteringAction::Keep => |c, ipaddr_tuple| { - Ok(c.contains(&ipaddr_tuple.0) || c.contains(&ipaddr_tuple.1)) - }, - FilteringAction::Drop => |c, ipaddr_tuple| { - Ok(!c.contains(&ipaddr_tuple.0) && !c.contains(&ipaddr_tuple.1)) + let keep: KeepFn = match filtering_action { + FilteringAction::Keep => { + |c, ipaddr_pair| Ok(c.contains(&ipaddr_pair.0) || c.contains(&ipaddr_pair.1)) + } + FilteringAction::Drop => |c, ipaddr_pair| { + Ok(!c.contains(&ipaddr_pair.0) && !c.contains(&ipaddr_pair.1)) }, }; diff --git a/pcap-rewrite/src/filters/ipaddr_pair.rs b/pcap-rewrite/src/filters/ipaddr_pair.rs new file mode 100644 index 0000000..12cf37f --- /dev/null +++ b/pcap-rewrite/src/filters/ipaddr_pair.rs @@ -0,0 +1,9 @@ +use std::net::IpAddr; + +pub struct IpAddrPair (pub IpAddr,pub IpAddr); + +impl IpAddrPair { + pub fn new(ipaddr_0: IpAddr, ipaddr_1: IpAddr) -> IpAddrPair { + IpAddrPair (ipaddr_0, ipaddr_1 ) + } +} diff --git a/pcap-rewrite/src/filters/key_parser_ipv4.rs b/pcap-rewrite/src/filters/key_parser_ipv4.rs index 9445c05..11ee058 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv4.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv4.rs @@ -12,6 +12,7 @@ use libpcap_tools::{Error, FiveTuple, ParseContext}; use super::fragmentation::two_tuple_proto_ipid::TwoTupleProtoIpid; use super::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; use crate::container::ipaddr_proto_port_container::IpAddrProtoPort; +use crate::filters::ipaddr_pair::IpAddrPair; pub fn parse_src_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result { let ipv4 = Ipv4Packet::new(payload).ok_or_else(|| { @@ -35,7 +36,7 @@ pub fn parse_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result Result<(IpAddr, IpAddr), Error> { +pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result { let ipv4_packet = Ipv4Packet::new(payload).ok_or_else(|| { warn!( "Expected Ipv4 packet but could not parse at index {}", @@ -45,7 +46,7 @@ pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result<(IpAdd })?; let src_ipaddr = IpAddr::V4(ipv4_packet.get_source()); let dst_ipaddr = IpAddr::V4(ipv4_packet.get_destination()); - Result::Ok((src_ipaddr, dst_ipaddr)) + Result::Ok(IpAddrPair::new(src_ipaddr, dst_ipaddr)) } pub fn parse_src_ipaddr_proto_dst_port( diff --git a/pcap-rewrite/src/filters/key_parser_ipv6.rs b/pcap-rewrite/src/filters/key_parser_ipv6.rs index 3c8823c..77620dd 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv6.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv6.rs @@ -12,6 +12,7 @@ use libpcap_tools::{Error, FiveTuple, ParseContext}; use super::fragmentation::two_tuple_proto_ipid::TwoTupleProtoIpid; use super::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; +use crate::filters::ipaddr_pair::IpAddrPair; pub fn parse_src_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result { let ipv6 = Ipv6Packet::new(payload).ok_or_else(|| { @@ -35,7 +36,7 @@ pub fn parse_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result Result<(IpAddr, IpAddr), Error> { +pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result { let ipv6_packet = Ipv6Packet::new(payload).ok_or_else(|| { warn!( "Expected Ipv6 packet but could not parse at index {}", @@ -45,7 +46,7 @@ pub fn parse_src_dst_ipaddr(ctx: &ParseContext, payload: &[u8]) -> Result<(IpAdd })?; let src_ipaddr = IpAddr::V6(ipv6_packet.get_source()); let dst_ipaddr = IpAddr::V6(ipv6_packet.get_destination()); - Result::Ok((src_ipaddr, dst_ipaddr)) + Result::Ok(IpAddrPair::new(src_ipaddr, dst_ipaddr)) } pub fn parse_src_ipaddr_proto_dst_port( diff --git a/pcap-rewrite/src/filters/mod.rs b/pcap-rewrite/src/filters/mod.rs index 5a198a9..29efb33 100644 --- a/pcap-rewrite/src/filters/mod.rs +++ b/pcap-rewrite/src/filters/mod.rs @@ -5,6 +5,7 @@ pub mod filter_utils; pub mod filtering_action; pub mod filtering_key; pub mod fragmentation; +pub mod ipaddr_pair; pub mod ipv6_utils; pub mod key_parser_ipv4; pub mod key_parser_ipv6;