diff --git a/pcap-rewrite/src/filters/common_filters.rs b/pcap-rewrite/src/filters/common_filters.rs index 946aaff..d075697 100644 --- a/pcap-rewrite/src/filters/common_filters.rs +++ b/pcap-rewrite/src/filters/common_filters.rs @@ -1,5 +1,5 @@ use crate::filters::filter::*; -use libpcap_tools::ParseContext; +use libpcap_tools::{Error,ParseContext}; use pcap_parser::data::{PacketData, ETHERTYPE_IPV4, ETHERTYPE_IPV6}; use pnet_packet::ethernet::EthernetPacket; use pnet_packet::ipv4::Ipv4Packet; @@ -18,7 +18,7 @@ pub struct IPFilter { } impl Filter for IPFilter { - fn filter<'i>(&self, _ctx: &ParseContext, i: PacketData<'i>) -> FResult, String> { + fn filter<'i>(&self, _ctx: &ParseContext, i: PacketData<'i>) -> FResult, Error> { match i { PacketData::L2(data) => { let p = match EthernetPacket::new(data) { @@ -56,7 +56,9 @@ impl Filter for IPFilter { } } PacketData::L4(_, _) => Err("Cannot filter IP, L4 content")?, - PacketData::Unsupported(_) => Err("Cannot filter IP, unsupported data".to_owned()), + PacketData::Unsupported(_) => { + Err(Error::Unsupported("Cannot filter IP, unsupported data")) + } } } } @@ -104,7 +106,7 @@ pub struct SourceFilter { } impl Filter for SourceFilter { - fn filter<'i>(&self, _ctx: &ParseContext, i: PacketData<'i>) -> FResult, String> { + fn filter<'i>(&self, _ctx: &ParseContext, i: PacketData<'i>) -> FResult, Error> { match i { PacketData::L2(data) => { let p = match EthernetPacket::new(data) { @@ -124,8 +126,10 @@ impl Filter for SourceFilter { Ok(Verdict::Drop) } } - PacketData::L4(_, _) => Err("Cannot filter source, L4 content".to_string()), - PacketData::Unsupported(_) => Err("Cannot filter source, unsupported data".to_string()), + PacketData::L4(_, _) => Err(Error::Unsupported("Cannot filter source, L4 content")), + PacketData::Unsupported(_) => { + Err(Error::Unsupported("Cannot filter source, unsupported data")) + } } } } diff --git a/pcap-rewrite/src/filters/dispatch_filter.rs b/pcap-rewrite/src/filters/dispatch_filter.rs index bcff120..3d930dc 100644 --- a/pcap-rewrite/src/filters/dispatch_filter.rs +++ b/pcap-rewrite/src/filters/dispatch_filter.rs @@ -1,8 +1,9 @@ use std::io; use std::net::IpAddr; use std::path::Path; +use log::warn; -use libpcap_tools::{FiveTuple, ParseContext}; +use libpcap_tools::{Error, FiveTuple, ParseContext}; use pcap_parser::data::PacketData; use pnet_packet::ethernet::{EtherType, EtherTypes}; use pnet_packet::ip::IpNextHeaderProtocol; @@ -19,9 +20,9 @@ use crate::filters::key_parser_ipv4; use crate::filters::key_parser_ipv6; /// Function to extract key from data -pub type GetKeyFn = Box Result>; +pub type GetKeyFn = Box Result>; /// Function to keep/drop extract key from container -pub type KeepFn = Box Result>; +pub type KeepFn = Box Result>; pub struct DispatchFilter { key_container: Container, @@ -49,11 +50,11 @@ impl DispatchFilter { &self, _ctx: &ParseContext, packet_data: PacketData<'j>, - ) -> FResult, String> { + ) -> FResult, Error> { let key = match packet_data { PacketData::L2(data) => { if data.len() < 14 { - return Err("L2 data too small for ethernet".to_owned()); + return Err(Error::DataParser("L2 data too small for ethernet")); } filter_utils::extract_callback_ethernet( @@ -67,11 +68,14 @@ impl DispatchFilter { match ether_type { EtherTypes::Ipv4 => (self.get_key_from_ipv4_l3_data)(data)?, EtherTypes::Ipv6 => (self.get_key_from_ipv4_l3_data)(data)?, - _ => Err(format!( - "Unimplemented Ethertype in L3 {:?}/{:x}", - ether_type, - ether_type.to_primitive_values().0 - ))?, + _ => { + warn!( + "Unimplemented Ethertype in L3 {:?}/{:x}", + ether_type, + ether_type.to_primitive_values().0 + ); + Err(Error::Unimplemented("Unimplemented Ethertype in L3"))? + } } } PacketData::L4(_, _) => unimplemented!(), @@ -92,7 +96,7 @@ impl DispatchFilter { } impl Filter for DispatchFilter { - fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, String> { + fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, Error> { self.keep(ctx, i) } } diff --git a/pcap-rewrite/src/filters/filter.rs b/pcap-rewrite/src/filters/filter.rs index 9cb9608..b3b6aac 100644 --- a/pcap-rewrite/src/filters/filter.rs +++ b/pcap-rewrite/src/filters/filter.rs @@ -1,4 +1,4 @@ -use libpcap_tools::{Packet,ParseContext}; +use libpcap_tools::{Error,Packet,ParseContext}; use pcap_parser::data::PacketData; /// Verdict emitted by a Filter @@ -13,7 +13,7 @@ pub enum Verdict { pub type FResult = Result, E>; pub trait Filter { - fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, String>; + fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, Error>; /// Does this filter plugin require a first pass to pre-analyze data? (default: `false`) fn require_pre_analysis(&self) -> bool { @@ -25,11 +25,11 @@ pub trait Filter { /// Any error raised in this function is fatal /// /// Note: packet content can be accessed in `packet.data` - fn pre_analyze(&mut self, _packet: &Packet) -> Result<(), String> { + fn pre_analyze(&mut self, _packet: &Packet) -> Result<(), Error> { Ok(()) } - fn preanalysis_done(&mut self) -> Result<(), String> { + fn preanalysis_done(&mut self) -> Result<(), Error> { Ok(()) } } @@ -38,7 +38,7 @@ pub fn apply_filters<'d>( filters: &'d [Box], ctx: &ParseContext, data: PacketData<'d>, -) -> FResult, String> { +) -> FResult, Error> { filters.iter().try_fold(Verdict::Accept(data), |d, f| { if let Verdict::Accept(data) = d { f.filter(ctx, data) diff --git a/pcap-rewrite/src/filters/filter_utils.rs b/pcap-rewrite/src/filters/filter_utils.rs index 2f5086b..0198c7c 100644 --- a/pcap-rewrite/src/filters/filter_utils.rs +++ b/pcap-rewrite/src/filters/filter_utils.rs @@ -1,36 +1,47 @@ +use log::warn; + +use libpcap_tools::Error; use pnet_packet::ethernet::{EtherTypes, EthernetPacket}; use pnet_packet::vlan::VlanPacket; use pnet_packet::Packet; use pnet_packet::PrimitiveValues; pub fn extract_callback_ethernet( - get_key_from_ipv4_l3_data: &dyn Fn(&[u8]) -> Result, - get_key_from_ipv6_l3_data: &dyn Fn(&[u8]) -> Result, + get_key_from_ipv4_l3_data: &dyn Fn(&[u8]) -> Result, + get_key_from_ipv6_l3_data: &dyn Fn(&[u8]) -> Result, packet_data: &[u8], -) -> Result { - let ethernet_packet = - EthernetPacket::new(packet_data).ok_or("Expected Ethernet packet but not found")?; +) -> Result { + let ethernet_packet = EthernetPacket::new(packet_data) + .ok_or(Error::Pnet("Expected Ethernet packet but could not parse"))?; match ethernet_packet.get_ethertype() { EtherTypes::Ipv4 => (get_key_from_ipv4_l3_data)(ethernet_packet.payload()), EtherTypes::Ipv6 => (get_key_from_ipv6_l3_data)(ethernet_packet.payload()), EtherTypes::Vlan => { // 802.11q let vlan_packet = VlanPacket::new(ethernet_packet.payload()) - .ok_or("Expected VLAN packet but not found")?; + .ok_or(Error::Pnet("Expected VLAN packet but could not parse"))?; match vlan_packet.get_ethertype() { EtherTypes::Ipv4 => (get_key_from_ipv4_l3_data)(ethernet_packet.payload()), EtherTypes::Ipv6 => (get_key_from_ipv6_l3_data)(ethernet_packet.payload()), - _ => Err(format!( - "Unimplemented Ethertype in 33024/802.11q: {:?}/{:x}", - vlan_packet.get_ethertype(), - vlan_packet.get_ethertype().to_primitive_values().0 - )), + _ => { + warn!( + "Unimplemented Ethertype in 33024/802.11q: {:?}/{:x}", + vlan_packet.get_ethertype(), + vlan_packet.get_ethertype().to_primitive_values().0 + ); + Err(Error::Unimplemented( + "Unimplemented Ethertype in 33024/802.11q", + )) + } } } - _ => Err(format!( - "Unimplemented Ethertype: {:?}/{:x}", - ethernet_packet.get_ethertype(), - ethernet_packet.get_ethertype().to_primitive_values().0 - )), + _ => { + warn!( + "Unimplemented Ethertype: {:?}/{:x}", + ethernet_packet.get_ethertype(), + ethernet_packet.get_ethertype().to_primitive_values().0 + ); + Err(Error::Unimplemented("Unimplemented Ethertype")) + } } } diff --git a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs index ab68682..2f06004 100644 --- a/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs +++ b/pcap-rewrite/src/filters/fragmentation/fragmentation_filter.rs @@ -2,11 +2,12 @@ use std::collections::HashSet; use std::io; 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::{Packet, ParseContext}; +use libpcap_tools::{Error, Packet, ParseContext}; use crate::container::five_tuple_container::FiveTupleC; use crate::container::ipaddr_container::IpAddrC; @@ -28,9 +29,9 @@ use super::convert_fn; /// Function to convert TwoTupleProtoIpid/FiveTuple data to key container pub type ConvertFn = Box) -> Container>; /// Function to extract key from data -pub type GetKeyFn = Box Result>; +pub type GetKeyFn = Box Result>; /// Function to keep/drop extract key from container -pub type KeepFn = Box Result>; +pub type KeepFn = Box Result>; pub struct FragmentationFilter { data_hs: HashSet, @@ -63,13 +64,13 @@ impl FragmentationFilter { } } - fn test_fragmentation_and_save(&mut self, packet: &Packet) -> Result<(), String> { + fn test_fragmentation_and_save(&mut self, packet: &Packet) -> Result<(), Error> { // Note: we only test the first fragment to be sure to capture the IP ID value. // Subsequent fragment with TCP/UDP/ICMP are always dropped because header parsing fails on all packets/fragments after the first. let is_first_fragment = match packet.data { PacketData::L2(data) => { if data.len() < 14 { - return Err("L2 data too small for ethernet".to_string()); + return Err(Error::DataParser("L2 data too small for ethernet")); } filter_utils::extract_callback_ethernet( @@ -83,7 +84,13 @@ impl FragmentationFilter { match ether_type { EtherTypes::Ipv4 => (fragmentation_test::is_ipv4_first_fragment)(data)?, EtherTypes::Ipv6 => (fragmentation_test::is_ipv6_first_fragment)(data)?, - _ => return Err(format!("{} is not implmented", ether_type)), + _ => { + warn!( + "Unimplemented Ethertype in L3: {:?}/{:x}", + ether_type, ether_type.0 + ); + return Err(Error::Unimplemented("Unimplemented EtherType in L3")); + } } } PacketData::L4(_, _) => unimplemented!(), @@ -94,7 +101,7 @@ impl FragmentationFilter { let data_option: Option = match packet.data { PacketData::L2(data) => { if data.len() < 14 { - return Err("L2 data too small for ethernet".to_string()); + return Err(Error::DataParser("L2 data too small for ethernet")); } Some(filter_utils::extract_callback_ethernet( @@ -113,10 +120,11 @@ impl FragmentationFilter { (key_parser_ipv6::parse_two_tuple_proto_ipid_five_tuple)(data)?, ), _ => { - return Err(format!( - "Unimplemented Ethertype in L3 {:?}/{:x}", + warn!( + "Unimplemented Ethertype in L3: {:?}/{:x}", ether_type, ether_type.0 - )) + ); + return Err(Error::Unimplemented("Unimplemented Ethertype in L3")); } } } @@ -136,11 +144,11 @@ impl FragmentationFilter { &self, _ctx: &ParseContext, packet_data: PacketData<'j>, - ) -> FResult, String> { + ) -> FResult, Error> { let key = match packet_data { PacketData::L2(data) => { if data.len() < 14 { - return Err("L2 data too small for ethernet".to_owned()); + return Err(Error::DataParser("L2 data too small for ethernet")); } filter_utils::extract_callback_ethernet( @@ -154,10 +162,13 @@ impl FragmentationFilter { match ether_type { EtherTypes::Ipv4 => (self.get_key_from_ipv4_l3_data)(data)?, EtherTypes::Ipv6 => (self.get_key_from_ipv6_l3_data)(data)?, - _ => Err(format!( - "Unimplemented Ethertype in L3 {:?}/{:x}", - ether_type, ether_type.0 - ))?, + _ => { + warn!( + "Unimplemented Ethertype in L3: {:?}/{:x}", + ether_type, ether_type.0 + ); + return Err(Error::Unimplemented("Unimplemented Ethertype in L3")); + } } } PacketData::L4(_, _) => unimplemented!(), @@ -178,7 +189,7 @@ impl FragmentationFilter { } impl Filter for FragmentationFilter { - fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, String> { + fn filter<'i>(&self, ctx: &ParseContext, i: PacketData<'i>) -> FResult, Error> { self.keep(ctx, i) } @@ -186,11 +197,11 @@ impl Filter for FragmentationFilter { true } - fn pre_analyze(&mut self, _packet: &Packet) -> Result<(), String> { + fn pre_analyze(&mut self, _packet: &Packet) -> Result<(), Error> { self.test_fragmentation_and_save(_packet) } - fn preanalysis_done(&mut self) -> Result<(), String> { + fn preanalysis_done(&mut self) -> Result<(), Error> { self.key_container = (self.convert_data_hs_c)(&self.data_hs); Ok(()) } @@ -199,7 +210,7 @@ impl Filter for FragmentationFilter { pub fn test_two_tuple_proto_ipid_five_tuple_option_in_container( container_tuple: &(TwoTupleProtoIpidC, FiveTupleC), two_tuple_proto_ipid_five_tuple: &TwoTupleProtoIpidFiveTuple, -) -> Result { +) -> Result { let (two_tuple_proto_ipid_c, five_tuple_c) = container_tuple; let in_0 = match two_tuple_proto_ipid_five_tuple.get_two_tuple_proto_ipid_option() { diff --git a/pcap-rewrite/src/filters/fragmentation/fragmentation_test.rs b/pcap-rewrite/src/filters/fragmentation/fragmentation_test.rs index efa74d3..467fbb9 100644 --- a/pcap-rewrite/src/filters/fragmentation/fragmentation_test.rs +++ b/pcap-rewrite/src/filters/fragmentation/fragmentation_test.rs @@ -1,10 +1,12 @@ +use libpcap_tools::Error; + use pnet_packet::ipv4::Ipv4Packet; use pnet_packet::ipv6::Ipv6Packet; use crate::filters::ipv6_utils; -pub fn is_ipv4_first_fragment(payload: &[u8]) -> Result { - let ipv4_packet = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +pub fn is_ipv4_first_fragment(payload: &[u8]) -> Result { + let ipv4_packet = Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; let flags = ipv4_packet.get_flags(); let fragment_offset = ipv4_packet.get_fragment_offset(); @@ -13,8 +15,8 @@ pub fn is_ipv4_first_fragment(payload: &[u8]) -> Result { Ok(mf_flag == 1 && fragment_offset == 0) } -pub fn is_ipv6_first_fragment(payload: &[u8]) -> Result { - let ipv6_packet = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn is_ipv6_first_fragment(payload: &[u8]) -> Result { + let ipv6_packet = Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; let (fragment_packet_option, _l4_proto, _payload) = ipv6_utils::get_fragment_packet_option_l4_protol4_payload(payload, &ipv6_packet)?; match fragment_packet_option { diff --git a/pcap-rewrite/src/filters/ipv6_utils.rs b/pcap-rewrite/src/filters/ipv6_utils.rs index ac93f4c..f0c2c4d 100644 --- a/pcap-rewrite/src/filters/ipv6_utils.rs +++ b/pcap-rewrite/src/filters/ipv6_utils.rs @@ -9,6 +9,8 @@ use pnet_packet::PacketSize; use pnet_packet::ip::IpNextHeaderProtocol; use pnet_packet::ip::IpNextHeaderProtocols; +use libpcap_tools::Error; + // TODO: factorize with code at URL below // From https://github.com/rusticata/pcap-analyzer/blob/3064dabbc51a19c51181dc223670ead34ce25844/libpcap-analyzer/src/analyzer.rs pub fn is_ipv6_opt(opt: IpNextHeaderProtocol) -> bool { @@ -27,7 +29,7 @@ pub fn is_ipv6_opt(opt: IpNextHeaderProtocol) -> bool { pub fn get_fragment_packet_option_l4_protol4_payload<'a>( data: &'a [u8], ipv6: &'a Ipv6Packet, -) -> Result<(Option>, IpNextHeaderProtocol, &'a [u8]), String> { +) -> Result<(Option>, IpNextHeaderProtocol, &'a [u8]), Error> { // From https://github.com/rusticata/pcap-analyzer/blob/3064dabbc51a19c51181dc223670ead34ce25844/libpcap-analyzer/src/analyzer.rs let mut payload = ipv6.payload(); let mut l4_proto = ipv6.get_next_header(); @@ -38,7 +40,7 @@ pub fn get_fragment_packet_option_l4_protol4_payload<'a>( if data.len() >= 40 { payload = &data[40..]; } else { - return Err("IPv6 length is 0, but frame is too short for an IPv6 header".to_string()); + return Err(Error::DataParser("IPv6 length is 0, but frame is too short for an IPv6 header")); } } @@ -57,7 +59,7 @@ pub fn get_fragment_packet_option_l4_protol4_payload<'a>( trace!("option header: {}", l4_proto); if l4_proto == IpNextHeaderProtocols::Ipv6Frag { if fragment_packet_option.is_some() { - return Err("multiple IPv6Frag extensions".to_string()); + return Err(Error::DataParser("multiple IPv6Frag extensions")); } fragment_packet_option = FragmentPacket::new(payload); } diff --git a/pcap-rewrite/src/filters/key_parser_ipv4.rs b/pcap-rewrite/src/filters/key_parser_ipv4.rs index 75b261e..f63ad82 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv4.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv4.rs @@ -7,23 +7,26 @@ use pnet_packet::tcp::TcpPacket; use pnet_packet::udp::UdpPacket; use pnet_packet::Packet; -use libpcap_tools::FiveTuple; +use libpcap_tools::{Error, FiveTuple}; use super::fragmentation::two_tuple_proto_ipid::TwoTupleProtoIpid; use super::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; -pub fn parse_src_ipaddr(payload: &[u8]) -> Result { - let ipv4 = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +pub fn parse_src_ipaddr(payload: &[u8]) -> Result { + let ipv4 = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; Result::Ok(IpAddr::V4(ipv4.get_source())) } -pub fn parse_dst_ipaddr(payload: &[u8]) -> Result { - let ipv4 = Ipv4Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_dst_ipaddr(payload: &[u8]) -> Result { + let ipv4 = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; Result::Ok(IpAddr::V4(ipv4.get_destination())) } -pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), String> { - let ipv4_packet = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), Error> { + let ipv4_packet = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; let src_ipaddr = IpAddr::V4(ipv4_packet.get_source()); let dst_ipaddr = IpAddr::V4(ipv4_packet.get_destination()); Result::Ok((src_ipaddr, dst_ipaddr)) @@ -31,8 +34,9 @@ pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), String> pub fn parse_src_ipaddr_proto_dst_port( payload: &[u8], -) -> Result<(IpAddr, IpNextHeaderProtocol, u16), String> { - let ipv4_packet = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +) -> Result<(IpAddr, IpNextHeaderProtocol, u16), Error> { + let ipv4_packet = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; let src_ipaddr = IpAddr::V4(ipv4_packet.get_source()); @@ -44,7 +48,9 @@ pub fn parse_src_ipaddr_proto_dst_port( let dst_port = tcp.get_destination(); Ok((src_ipaddr, IpNextHeaderProtocols::Tcp, dst_port)) } - None => Err("Expected TCP packet in Ipv4 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected TCP packet in Ipv4 but could not parse", + )), } } IpNextHeaderProtocols::Udp => match UdpPacket::new(ipv4_packet.payload()) { @@ -52,14 +58,17 @@ pub fn parse_src_ipaddr_proto_dst_port( let dst_port = udp.get_destination(); Ok((src_ipaddr, IpNextHeaderProtocols::Udp, dst_port)) } - None => Err("Expected UDP packet in Ipv4 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected UDP packet in Ipv4 but could not parse", + )), }, _ => Ok((src_ipaddr, ipv4_packet.get_next_level_protocol(), 0)), } } -pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result { - let ipv4_packet = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result { + let ipv4_packet = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; let src_ipaddr = IpAddr::V4(ipv4_packet.get_source()); let dst_ipaddr = IpAddr::V4(ipv4_packet.get_destination()); let proto = ipv4_packet.get_next_level_protocol().0; @@ -67,8 +76,9 @@ pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result Result { - let ipv4_packet = Ipv4Packet::new(payload).ok_or("Expected Ipv4 packet but not found")?; +pub fn parse_five_tuple(payload: &[u8]) -> Result { + let ipv4_packet = + Ipv4Packet::new(payload).ok_or(Error::Pnet("Expected Ipv4 packet but could not parse"))?; let src_ipaddr = IpAddr::V4(ipv4_packet.get_source()); let dst_ipaddr = IpAddr::V4(ipv4_packet.get_destination()); @@ -88,7 +98,9 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { dst_port, }) } - None => Err("Expected TCP packet in Ipv4 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected TCP packet in Ipv4 but could not parse", + )), } } IpNextHeaderProtocols::Udp => match UdpPacket::new(ipv4_packet.payload()) { @@ -103,7 +115,9 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { dst_port, }) } - None => Err("Expected UDP packet in Ipv4 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected UDP packet in Ipv4 but could not parse", + )), }, _ => Ok(FiveTuple { src: src_ipaddr, @@ -117,7 +131,7 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { pub fn parse_two_tuple_proto_ipid_five_tuple( payload: &[u8], -) -> Result { +) -> Result { let two_tuple_proto_ipid = parse_two_tuple_proto_ipid(payload)?; let five_tuple = parse_five_tuple(payload)?; let two_tuple_proto_ipid_five_tuple = diff --git a/pcap-rewrite/src/filters/key_parser_ipv6.rs b/pcap-rewrite/src/filters/key_parser_ipv6.rs index 0efdcf5..cce85f3 100644 --- a/pcap-rewrite/src/filters/key_parser_ipv6.rs +++ b/pcap-rewrite/src/filters/key_parser_ipv6.rs @@ -7,23 +7,26 @@ use pnet_packet::tcp::TcpPacket; use pnet_packet::udp::UdpPacket; use crate::filters::ipv6_utils; -use libpcap_tools::FiveTuple; +use libpcap_tools::{Error, FiveTuple}; use super::fragmentation::two_tuple_proto_ipid::TwoTupleProtoIpid; use super::fragmentation::two_tuple_proto_ipid_five_tuple::TwoTupleProtoIpidFiveTuple; -pub fn parse_src_ipaddr(payload: &[u8]) -> Result { - let ipv6 = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_src_ipaddr(payload: &[u8]) -> Result { + let ipv6 = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; Ok(IpAddr::V6(ipv6.get_source())) } -pub fn parse_dst_ipaddr(payload: &[u8]) -> Result { - let ipv6 = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_dst_ipaddr(payload: &[u8]) -> Result { + let ipv6 = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; Ok(IpAddr::V6(ipv6.get_destination())) } -pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), String> { - let ipv6_packet = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), Error> { + let ipv6_packet = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; let src_ipaddr = IpAddr::V6(ipv6_packet.get_source()); let dst_ipaddr = IpAddr::V6(ipv6_packet.get_destination()); Result::Ok((src_ipaddr, dst_ipaddr)) @@ -31,8 +34,9 @@ pub fn parse_src_dst_ipaddr(payload: &[u8]) -> Result<(IpAddr, IpAddr), String> pub fn parse_src_ipaddr_proto_dst_port( payload: &[u8], -) -> Result<(IpAddr, IpNextHeaderProtocol, u16), String> { - let ipv6_packet = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +) -> Result<(IpAddr, IpNextHeaderProtocol, u16), Error> { + let ipv6_packet = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; let src_ipaddr = IpAddr::V6(ipv6_packet.get_source()); @@ -45,21 +49,26 @@ pub fn parse_src_ipaddr_proto_dst_port( let dst_port = tcp.get_destination(); Ok((src_ipaddr, IpNextHeaderProtocols::Tcp, dst_port)) } - None => Err("Expected TCP packet in Ipv6 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected TCP packet in Ipv6 but could not parse", + )), }, IpNextHeaderProtocols::Udp => match UdpPacket::new(payload) { Some(ref udp) => { let dst_port = udp.get_destination(); Ok((src_ipaddr, IpNextHeaderProtocols::Udp, dst_port)) } - None => Err("Expected UDP packet in Ipv6 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected UDP packet in Ipv6 but could not parse", + )), }, _ => Ok((src_ipaddr, l4_proto, 0)), } } -pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result, String> { - let ipv6_packet = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result, Error> { + let ipv6_packet = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; let src_ipaddr = IpAddr::V6(ipv6_packet.get_destination()); let dst_ipaddr = IpAddr::V6(ipv6_packet.get_destination()); @@ -79,8 +88,9 @@ pub fn parse_two_tuple_proto_ipid(payload: &[u8]) -> Result Result { - let ipv6_packet = Ipv6Packet::new(payload).ok_or("Expected Ipv6 packet but not found")?; +pub fn parse_five_tuple(payload: &[u8]) -> Result { + let ipv6_packet = + Ipv6Packet::new(payload).ok_or(Error::Pnet("Expected Ipv6 packet but could not parse"))?; let src_ipaddr = IpAddr::V6(ipv6_packet.get_source()); let dst_ipaddr = IpAddr::V6(ipv6_packet.get_destination()); @@ -101,7 +111,9 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { dst_port, }) } - None => Err("Expected TCP packet in Ipv6 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected TCP packet in Ipv6 but could not parse", + )), }, IpNextHeaderProtocols::Udp => match UdpPacket::new(payload) { Some(ref udp) => { @@ -115,7 +127,9 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { dst_port, }) } - None => Err("Expected UDP packet in Ipv6 but could not parse".to_string()), + None => Err(Error::Pnet( + "Expected UDP packet in Ipv6 but could not parse", + )), }, _ => Ok(FiveTuple { src: src_ipaddr, @@ -129,7 +143,7 @@ pub fn parse_five_tuple(payload: &[u8]) -> Result { pub fn parse_two_tuple_proto_ipid_five_tuple( payload: &[u8], -) -> Result { +) -> Result { Ok(TwoTupleProtoIpidFiveTuple::new( parse_two_tuple_proto_ipid(payload)?, // TODO: replace by dedicated error type to distinguish between Ipv6Packet parsing error and TcpPacket/UdpPacket error related to fragmentation