diff --git a/src/nat/mod.rs b/src/nat/mod.rs index 3e12c7d..c2e70fb 100644 --- a/src/nat/mod.rs +++ b/src/nat/mod.rs @@ -1,14 +1,14 @@ -use self::{ - // interface::Nat64Interface, - packet::IpPacket, - table::{Nat64Table, TableError}, +use crate::packet::protocols::{ + icmp::IcmpPacket, icmpv6::Icmpv6Packet, ipv4::Ipv4Packet, ipv6::Ipv6Packet, raw::RawBytes, + tcp::TcpPacket, udp::UdpPacket, }; -use crate::{ - into_icmp, into_icmpv6, into_tcp, into_udp, ipv4_packet, ipv6_packet, - nat::xlat::translate_udp_4_to_6, + +use self::{ + table::Nat64Table, + utils::{embed_address, extract_address}, }; use ipnet::{Ipv4Net, Ipv6Net}; -use pnet_packet::{ip::IpNextHeaderProtocols, Packet}; +use pnet_packet::ip::IpNextHeaderProtocols; use protomask_tun::TunDevice; use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr}, @@ -18,8 +18,9 @@ use tokio::sync::{broadcast, mpsc}; mod interface; mod macros; -mod packet; +// mod packet; mod table; +mod utils; mod xlat; #[derive(Debug, thiserror::Error)] @@ -33,6 +34,8 @@ pub enum Nat64Error { #[error(transparent)] XlatError(#[from] xlat::PacketTranslationError), #[error(transparent)] + PacketHandlingError(#[from] crate::packet::error::PacketError), + #[error(transparent)] PacketReceiveError(#[from] broadcast::error::RecvError), } @@ -84,219 +87,130 @@ impl Nat64 { // Try to read a packet let packet = rx.recv().await?; - - - // Spawn a task to process the packet + // Clone the TX so the worker can respond with data let mut tx = tx.clone(); - tokio::spawn(async move{ + // Separate logic is needed for handling IPv4 vs IPv6 packets, so a check must be done here + match packet[0] >> 4 { + 4 => { + // Parse the packet + let packet: Ipv4Packet> = packet.try_into()?; - }); + // Drop packets that aren't destined for a destination the table knows about + if !self.table.contains(&IpAddr::V4(packet.destination_address)) { + continue; + } + + // Get the new source and dest addresses + let new_source = embed_address(packet.source_address, self.ipv6_nat_prefix); + let new_destination = self.table.get_reverse(packet.destination_address)?; + + // Spawn a task to process the packet + tokio::spawn(async move { + process_inbound_ipv4(packet, new_source, new_destination, &mut tx) + .await + .unwrap(); + }); + } + 6 => { + // Parse the packet + let packet: Ipv6Packet> = packet.try_into()?; + + // Get the new source and dest addresses + let new_source = self.table.get_or_assign_ipv4(packet.source_address)?; + let new_destination = extract_address(packet.destination_address); + + // Spawn a task to process the packet + tokio::spawn(async move { + process_inbound_ipv6(packet, new_source, new_destination, &mut tx) + .await + .unwrap(); + }); + } + n => { + log::warn!("Unknown IP version: {}", n); + } + } } Ok(()) - // // Allocate a buffer for incoming packets - // let mut buffer = vec![0u8; self.interface.mtu()]; - - // // Loop forever - // loop { - // // Read a packet from the interface - // match self.interface.recv(&mut buffer) { - // Ok(packet_len) => { - // // Parse in to a more friendly format - // log::debug!("--- NEW PACKET ---"); - // match IpPacket::new(&buffer[..packet_len]) { - // // Try to process the packet - // Ok(inbound_packet) => match self.process_packet(inbound_packet).await { - // Ok(outbound_packet) => match outbound_packet { - // // If data is returned, send it back out the interface - // Some(outbound_packet) => { - // let packet_bytes = outbound_packet.to_bytes(); - // log::debug!( - // "Outbound packet next header: {}", - // outbound_packet.get_next_header().0 - // ); - // log::debug!("Sending packet: {:?}", packet_bytes); - // self.interface.send(&packet_bytes).unwrap(); - // } - // // Otherwise, we can assume that the packet was dealt with, and can move on - // None => {} - // }, - - // // Some errors are non-critical as far as this loop is concerned - // Err(error) => match error { - // Nat64Error::TableError(TableError::NoIpv6Mapping(address)) => { - // log::debug!("No IPv6 mapping for {}", address); - // } - // error => { - // return Err(error); - // } - // }, - // }, - // Err(error) => { - // log::error!("Failed to parse packet: {}", error); - // } - // } - // } - // Err(error) => { - // log::error!("Failed to read packet: {}", error); - // } - // } - // } } } -impl Nat64 { - - async fn process_packet<'a>( - &mut self, - packet: IpPacket<'a>, - ) -> Result>, Nat64Error> { - // The destination of the packet must be within a prefix we care about - if match packet.get_destination() { - IpAddr::V4(ipv4_addr) => !self.table.is_address_within_pool(&ipv4_addr), - IpAddr::V6(ipv6_addr) => !self.ipv6_nat_prefix.contains(&ipv6_addr), - } { - log::debug!( - "Packet destination {} is not within the NAT64 prefix or IPv4 pool", - packet.get_destination(), - ); - return Ok(None); +/// Process an inbound IPv4 packet +async fn process_inbound_ipv4( + packet: Ipv4Packet>, + new_source: Ipv6Addr, + new_destination: Ipv6Addr, + tx: &mut mpsc::Sender>, +) -> Result<(), Nat64Error> { + // Handle each possible embedded packet type + match packet.protocol { + IpNextHeaderProtocols::Icmp => { + let icmp_packet: IcmpPacket = packet.payload.try_into()?; + todo!() } - - // Compute the translated source and dest addresses - let source = packet.get_source(); - let new_source = self - .table - .calculate_xlat_addr(&source, &self.ipv6_nat_prefix)?; - let destination = packet.get_destination(); - let new_destination = self - .table - .calculate_xlat_addr(&destination, &self.ipv6_nat_prefix)?; - - // Log information about the packet - log::debug!( - "Received packet traveling from {} to {}", - source, - destination - ); - log::debug!( - "New path shall become: {} -> {}", - new_source, - new_destination - ); - - // Different logic is required for ICMP, UDP, and TCP - match (packet, new_source, new_destination) { - (IpPacket::V4(packet), IpAddr::V6(new_source), IpAddr::V6(new_destination)) => { - match packet.get_next_level_protocol() { - // Internet Control Message Protocol - IpNextHeaderProtocols::Icmp => match xlat::translate_icmp_4_to_6( - into_icmp!(packet.payload().to_vec())?, - new_source, - new_destination, - )? { - Some(icmp_packet) => Ok(Some(IpPacket::V6(ipv6_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Icmpv6, - packet.get_ttl(), - icmp_packet.packet() - )))), - None => Ok(None), - }, - - // User Datagram Protocol - IpNextHeaderProtocols::Udp => Ok(Some(IpPacket::V6(ipv6_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Udp, - packet.get_ttl(), - translate_udp_4_to_6( - into_udp!(packet.payload().to_vec())?, - new_source, - new_destination - )? - .packet() - )))), - - // Transmission Control Protocol - IpNextHeaderProtocols::Tcp => Ok(Some(IpPacket::V6(ipv6_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Tcp, - packet.get_ttl(), - xlat::translate_tcp_4_to_6( - into_tcp!(packet.payload().to_vec())?, - new_source, - new_destination - )? - .packet() - )))), - - // For any protocol we don't support, just warn and drop the packet - next_level_protocol => { - log::warn!("Unsupported next level protocol: {}", next_level_protocol); - Ok(None) - } - } - } - (IpPacket::V6(packet), IpAddr::V4(new_source), IpAddr::V4(new_destination)) => { - match packet.get_next_header() { - // Internet Control Message Protocol Version 6 - IpNextHeaderProtocols::Icmpv6 => match xlat::translate_icmp_6_to_4( - into_icmpv6!(packet.payload().to_vec())?, - new_source, - new_destination, - )? { - Some(icmp_packet) => Ok(Some(IpPacket::V4(ipv4_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Icmp, - packet.get_hop_limit(), - icmp_packet.packet() - )))), - None => Ok(None), - }, - - // User Datagram Protocol - IpNextHeaderProtocols::Udp => Ok(Some(IpPacket::V4(ipv4_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Udp, - packet.get_hop_limit(), - xlat::translate_udp_6_to_4( - into_udp!(packet.payload().to_vec())?, - new_source, - new_destination - )? - .packet() - )))), - - // Transmission Control Protocol - IpNextHeaderProtocols::Tcp => Ok(Some(IpPacket::V4(ipv4_packet!( - new_source, - new_destination, - IpNextHeaderProtocols::Tcp, - packet.get_hop_limit(), - xlat::translate_tcp_6_to_4( - into_tcp!(packet.payload().to_vec())?, - new_source, - new_destination - )? - .packet() - )))), - - // For any protocol we don't support, just warn and drop the packet - next_header_protocol => { - log::warn!("Unsupported next header protocol: {}", next_header_protocol); - Ok(None) - } - } - } - - // Honestly, this should probably be `unreachable!()` - _ => unimplemented!(), + IpNextHeaderProtocols::Udp => { + let udp_packet: UdpPacket = UdpPacket::new_from_bytes_raw_payload( + &packet.payload, + IpAddr::V4(packet.source_address), + IpAddr::V4(packet.destination_address), + )?; + todo!() + } + IpNextHeaderProtocols::Tcp => { + let tcp_packet: TcpPacket = TcpPacket::new_from_bytes_raw_payload( + &packet.payload, + IpAddr::V4(packet.source_address), + IpAddr::V4(packet.destination_address), + )?; + todo!() + } + _ => { + log::warn!("Unsupported next level protocol: {}", packet.protocol); } } + + Ok(()) +} + +/// Process an inbound IPv6 packet +async fn process_inbound_ipv6( + packet: Ipv6Packet>, + new_source: Ipv4Addr, + new_destination: Ipv4Addr, + tx: &mut mpsc::Sender>, +) -> Result<(), Nat64Error> { + // Handle each possible embedded packet type + match packet.next_header { + IpNextHeaderProtocols::Icmpv6 => { + let icmpv6_packet: Icmpv6Packet = Icmpv6Packet::new_from_bytes_raw_payload( + &packet.payload, + packet.source_address, + packet.destination_address, + )?; + todo!() + } + IpNextHeaderProtocols::Udp => { + let udp_packet: UdpPacket = UdpPacket::new_from_bytes_raw_payload( + &packet.payload, + IpAddr::V6(packet.source_address), + IpAddr::V6(packet.destination_address), + )?; + todo!() + } + IpNextHeaderProtocols::Tcp => { + let tcp_packet: TcpPacket = TcpPacket::new_from_bytes_raw_payload( + &packet.payload, + IpAddr::V6(packet.source_address), + IpAddr::V6(packet.destination_address), + )?; + todo!() + } + _ => { + log::warn!("Unsupported next level protocol: {}", packet.next_header); + } + } + + Ok(()) } diff --git a/src/nat/packet.rs b/src/nat/packet.rs index d69934f..dc8ab37 100644 --- a/src/nat/packet.rs +++ b/src/nat/packet.rs @@ -1,159 +1,159 @@ -//! A generic internet protocol packet type +// //! A generic internet protocol packet type -use std::net::IpAddr; +// use std::net::IpAddr; -use pnet_packet::{ip::IpNextHeaderProtocol, ipv4::Ipv4Packet, ipv6::Ipv6Packet, Packet}; +// use pnet_packet::{ip::IpNextHeaderProtocol, ipv4::Ipv4Packet, ipv6::Ipv6Packet, Packet}; -#[derive(Debug, thiserror::Error)] -pub enum PacketError { - #[error("Packed too small (len: {0})")] - PacketTooSmall(usize), - #[error("Unknown Internet Protocol version: {0}")] - UnknownVersion(u8), -} +// #[derive(Debug, thiserror::Error)] +// pub enum PacketError { +// #[error("Packed too small (len: {0})")] +// PacketTooSmall(usize), +// #[error("Unknown Internet Protocol version: {0}")] +// UnknownVersion(u8), +// } -/// A protocol-agnostic packet type -#[derive(Debug)] -pub enum IpPacket<'a> { - /// IPv4 packet - V4(Ipv4Packet<'a>), - /// IPv6 packet - V6(Ipv6Packet<'a>), -} +// /// A protocol-agnostic packet type +// #[derive(Debug)] +// pub enum IpPacket<'a> { +// /// IPv4 packet +// V4(Ipv4Packet<'a>), +// /// IPv6 packet +// V6(Ipv6Packet<'a>), +// } -impl IpPacket<'_> { - /// Creates a new packet from a byte slice - pub fn new<'a>(bytes: &'a [u8]) -> Result, PacketError> { - // Parse the packet. If there is an error, cast None to the error type - match bytes[0] >> 4 { - 4 => Ok(IpPacket::V4( - Ipv4Packet::new(bytes).ok_or_else(|| PacketError::PacketTooSmall(bytes.len()))?, - )), - 6 => Ok(IpPacket::V6( - Ipv6Packet::new(bytes).ok_or_else(|| PacketError::PacketTooSmall(bytes.len()))?, - )), - n => Err(PacketError::UnknownVersion(n)), - } - } +// impl IpPacket<'_> { +// /// Creates a new packet from a byte slice +// pub fn new<'a>(bytes: &'a [u8]) -> Result, PacketError> { +// // Parse the packet. If there is an error, cast None to the error type +// match bytes[0] >> 4 { +// 4 => Ok(IpPacket::V4( +// Ipv4Packet::new(bytes).ok_or_else(|| PacketError::PacketTooSmall(bytes.len()))?, +// )), +// 6 => Ok(IpPacket::V6( +// Ipv6Packet::new(bytes).ok_or_else(|| PacketError::PacketTooSmall(bytes.len()))?, +// )), +// n => Err(PacketError::UnknownVersion(n)), +// } +// } - /// Returns the source address - pub fn get_source(&self) -> IpAddr { - match self { - IpPacket::V4(packet) => IpAddr::V4(packet.get_source()), - IpPacket::V6(packet) => IpAddr::V6(packet.get_source()), - } - } +// /// Returns the source address +// pub fn get_source(&self) -> IpAddr { +// match self { +// IpPacket::V4(packet) => IpAddr::V4(packet.get_source()), +// IpPacket::V6(packet) => IpAddr::V6(packet.get_source()), +// } +// } - /// Returns the destination address - pub fn get_destination(&self) -> IpAddr { - match self { - IpPacket::V4(packet) => IpAddr::V4(packet.get_destination()), - IpPacket::V6(packet) => IpAddr::V6(packet.get_destination()), - } - } +// /// Returns the destination address +// pub fn get_destination(&self) -> IpAddr { +// match self { +// IpPacket::V4(packet) => IpAddr::V4(packet.get_destination()), +// IpPacket::V6(packet) => IpAddr::V6(packet.get_destination()), +// } +// } - /// Returns the packet header - #[allow(dead_code)] - pub fn get_header(&self) -> &[u8] { - match self { - IpPacket::V4(packet) => packet.packet()[..20].as_ref(), - IpPacket::V6(packet) => packet.packet()[..40].as_ref(), - } - } +// /// Returns the packet header +// #[allow(dead_code)] +// pub fn get_header(&self) -> &[u8] { +// match self { +// IpPacket::V4(packet) => packet.packet()[..20].as_ref(), +// IpPacket::V6(packet) => packet.packet()[..40].as_ref(), +// } +// } - /// Returns the packet payload - #[allow(dead_code)] - pub fn get_payload(&self) -> &[u8] { - match self { - IpPacket::V4(packet) => packet.payload(), - IpPacket::V6(packet) => packet.payload(), - } - } +// /// Returns the packet payload +// #[allow(dead_code)] +// pub fn get_payload(&self) -> &[u8] { +// match self { +// IpPacket::V4(packet) => packet.payload(), +// IpPacket::V6(packet) => packet.payload(), +// } +// } - /// Converts the packet to a byte vector - pub fn to_bytes(&self) -> Vec { - match self { - IpPacket::V4(packet) => packet.packet().to_vec(), - IpPacket::V6(packet) => packet.packet().to_vec(), - } - } +// /// Converts the packet to a byte vector +// pub fn to_bytes(&self) -> Vec { +// match self { +// IpPacket::V4(packet) => packet.packet().to_vec(), +// IpPacket::V6(packet) => packet.packet().to_vec(), +// } +// } - /// Returns the packet length - #[allow(dead_code)] - pub fn len(&self) -> usize { - match self { - IpPacket::V4(packet) => packet.packet().len(), - IpPacket::V6(packet) => packet.packet().len(), - } - } +// /// Returns the packet length +// #[allow(dead_code)] +// pub fn len(&self) -> usize { +// match self { +// IpPacket::V4(packet) => packet.packet().len(), +// IpPacket::V6(packet) => packet.packet().len(), +// } +// } - /// Get the next header - pub fn get_next_header(&self) -> IpNextHeaderProtocol { - match self { - IpPacket::V4(packet) => packet.get_next_level_protocol(), - IpPacket::V6(packet) => packet.get_next_header(), - } - } +// /// Get the next header +// pub fn get_next_header(&self) -> IpNextHeaderProtocol { +// match self { +// IpPacket::V4(packet) => packet.get_next_level_protocol(), +// IpPacket::V6(packet) => packet.get_next_header(), +// } +// } - /// Get the TTL - #[allow(dead_code)] - pub fn get_ttl(&self) -> u8 { - match self { - IpPacket::V4(packet) => packet.get_ttl(), - IpPacket::V6(packet) => packet.get_hop_limit(), - } - } -} +// /// Get the TTL +// #[allow(dead_code)] +// pub fn get_ttl(&self) -> u8 { +// match self { +// IpPacket::V4(packet) => packet.get_ttl(), +// IpPacket::V6(packet) => packet.get_hop_limit(), +// } +// } +// } -#[cfg(test)] -mod tests { - use pnet_packet::{ipv4::MutableIpv4Packet, ipv6::MutableIpv6Packet}; +// #[cfg(test)] +// mod tests { +// use pnet_packet::{ipv4::MutableIpv4Packet, ipv6::MutableIpv6Packet}; - use super::*; +// use super::*; - #[test] - fn test_ipv4_packet() { - // Build packet to test - let mut packet = MutableIpv4Packet::owned(vec![0; 20]).unwrap(); - packet.set_version(4); - packet.set_source("192.0.2.1".parse().unwrap()); - packet.set_destination("192.0.2.2".parse().unwrap()); +// #[test] +// fn test_ipv4_packet() { +// // Build packet to test +// let mut packet = MutableIpv4Packet::owned(vec![0; 20]).unwrap(); +// packet.set_version(4); +// packet.set_source("192.0.2.1".parse().unwrap()); +// packet.set_destination("192.0.2.2".parse().unwrap()); - // Parse - let header = packet.packet()[..20].to_vec(); - let packet = IpPacket::new(packet.packet()).unwrap(); - assert_eq!( - packet.get_source(), - IpAddr::V4("192.0.2.1".parse().unwrap()) - ); - assert_eq!( - packet.get_destination(), - IpAddr::V4("192.0.2.2".parse().unwrap()) - ); - assert_eq!(packet.get_header(), header); - } +// // Parse +// let header = packet.packet()[..20].to_vec(); +// let packet = IpPacket::new(packet.packet()).unwrap(); +// assert_eq!( +// packet.get_source(), +// IpAddr::V4("192.0.2.1".parse().unwrap()) +// ); +// assert_eq!( +// packet.get_destination(), +// IpAddr::V4("192.0.2.2".parse().unwrap()) +// ); +// assert_eq!(packet.get_header(), header); +// } - #[test] - fn test_ipv6_packet() { - // Build packet to test - let mut packet = MutableIpv6Packet::owned(vec![0; 40]).unwrap(); - packet.set_version(6); - packet.set_source("2001:db8::c0a8:1".parse().unwrap()); - packet.set_destination("2001:db8::c0a8:2".parse().unwrap()); +// #[test] +// fn test_ipv6_packet() { +// // Build packet to test +// let mut packet = MutableIpv6Packet::owned(vec![0; 40]).unwrap(); +// packet.set_version(6); +// packet.set_source("2001:db8::c0a8:1".parse().unwrap()); +// packet.set_destination("2001:db8::c0a8:2".parse().unwrap()); - // Parse - let header = packet.packet()[..40].to_vec(); - let packet = IpPacket::new(packet.packet()).unwrap(); +// // Parse +// let header = packet.packet()[..40].to_vec(); +// let packet = IpPacket::new(packet.packet()).unwrap(); - // Test - assert_eq!( - packet.get_source(), - IpAddr::V6("2001:db8::c0a8:1".parse().unwrap()) - ); - assert_eq!( - packet.get_destination(), - IpAddr::V6("2001:db8::c0a8:2".parse().unwrap()) - ); - assert_eq!(packet.get_header(), header); - } -} +// // Test +// assert_eq!( +// packet.get_source(), +// IpAddr::V6("2001:db8::c0a8:1".parse().unwrap()) +// ); +// assert_eq!( +// packet.get_destination(), +// IpAddr::V6("2001:db8::c0a8:2".parse().unwrap()) +// ); +// assert_eq!(packet.get_header(), header); +// } +// } diff --git a/src/nat/table.rs b/src/nat/table.rs index 55b9f2e..30226f1 100644 --- a/src/nat/table.rs +++ b/src/nat/table.rs @@ -67,6 +67,14 @@ impl Nat64Table { Ok(()) } + /// Check if a given address exists in the table + pub fn contains(&self, address: &IpAddr) -> bool { + match address { + IpAddr::V4(ipv4) => self.reservations.contains_right(ipv4), + IpAddr::V6(ipv6) => self.reservations.contains_left(ipv6), + } + } + /// Get or assign an IPv4 address for the given IPv6 address pub fn get_or_assign_ipv4(&mut self, ipv6: Ipv6Addr) -> Result { // Prune old reservations diff --git a/src/nat/utils.rs b/src/nat/utils.rs new file mode 100644 index 0000000..47b15f6 --- /dev/null +++ b/src/nat/utils.rs @@ -0,0 +1,25 @@ +use std::net::{Ipv4Addr, Ipv6Addr}; + +use ipnet::Ipv6Net; + +/// Embed an IPv4 address in an IPv6 prefix +pub fn embed_address(ipv4_address: Ipv4Addr, ipv6_prefix: Ipv6Net) -> Ipv6Addr { + let v4_octets = ipv4_address.octets(); + let v6_octets = ipv6_prefix.addr().octets(); + Ipv6Addr::new( + u16::from_be_bytes([v6_octets[0], v6_octets[1]]), + u16::from_be_bytes([v6_octets[2], v6_octets[3]]), + u16::from_be_bytes([v6_octets[4], v6_octets[5]]), + u16::from_be_bytes([v6_octets[6], v6_octets[7]]), + u16::from_be_bytes([v6_octets[8], v6_octets[9]]), + u16::from_be_bytes([v6_octets[10], v6_octets[11]]), + u16::from_be_bytes([v4_octets[0], v4_octets[1]]), + u16::from_be_bytes([v4_octets[2], v4_octets[3]]), + ) +} + +/// Extract an IPv4 address from an IPv6 address +pub fn extract_address(ipv6_address: Ipv6Addr) -> Ipv4Addr { + let octets = ipv6_address.octets(); + Ipv4Addr::new(octets[12], octets[13], octets[14], octets[15]) +} diff --git a/src/packet/protocols/icmp.rs b/src/packet/protocols/icmp.rs index dd1ce40..dce1f92 100644 --- a/src/packet/protocols/icmp.rs +++ b/src/packet/protocols/icmp.rs @@ -43,6 +43,7 @@ where } } + impl Into> for IcmpPacket where T: Into>, diff --git a/src/packet/protocols/icmpv6.rs b/src/packet/protocols/icmpv6.rs index 0d9c095..75ebff6 100644 --- a/src/packet/protocols/icmpv6.rs +++ b/src/packet/protocols/icmpv6.rs @@ -7,6 +7,8 @@ use pnet_packet::{ use crate::packet::error::PacketError; +use super::raw::RawBytes; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Icmpv6Packet { pub source_address: Ipv6Addr, @@ -60,7 +62,7 @@ where } } -impl Icmpv6Packet> { +impl Icmpv6Packet { /// Construct a new ICMPv6 packet with a raw payload from raw bytes pub fn new_from_bytes_raw_payload( bytes: &[u8], @@ -77,7 +79,7 @@ impl Icmpv6Packet> { destination_address, icmp_type: packet.get_icmpv6_type(), icmp_code: packet.get_icmpv6_code(), - payload: packet.payload().to_vec(), + payload: RawBytes(packet.payload().to_vec()), }) } } diff --git a/src/packet/protocols/mod.rs b/src/packet/protocols/mod.rs index f02f380..ae58976 100644 --- a/src/packet/protocols/mod.rs +++ b/src/packet/protocols/mod.rs @@ -2,5 +2,6 @@ pub mod icmp; pub mod icmpv6; pub mod ipv4; pub mod ipv6; +pub mod raw; pub mod tcp; pub mod udp; diff --git a/src/packet/protocols/raw.rs b/src/packet/protocols/raw.rs new file mode 100644 index 0000000..95bca85 --- /dev/null +++ b/src/packet/protocols/raw.rs @@ -0,0 +1,12 @@ +use crate::packet::error::PacketError; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RawBytes(pub Vec); + +impl TryFrom> for RawBytes { + type Error = PacketError; + + fn try_from(bytes: Vec) -> Result { + Ok(Self(bytes)) + } +} diff --git a/src/packet/protocols/tcp.rs b/src/packet/protocols/tcp.rs index 087f237..97f94d1 100644 --- a/src/packet/protocols/tcp.rs +++ b/src/packet/protocols/tcp.rs @@ -5,6 +5,7 @@ use pnet_packet::{ Packet, }; +use super::raw::RawBytes; use crate::packet::error::PacketError; /// A TCP packet @@ -145,7 +146,7 @@ where } } -impl TcpPacket> { +impl TcpPacket { /// Construct a new TCP packet with a raw payload from bytes pub fn new_from_bytes_raw_payload( bytes: &[u8], @@ -174,7 +175,7 @@ impl TcpPacket> { window_size: parsed.get_window(), urgent_pointer: parsed.get_urgent_ptr(), options: parsed.get_options().to_vec(), - payload: parsed.payload().to_vec(), + payload: RawBytes(parsed.payload().to_vec()), }) } } diff --git a/src/packet/protocols/udp.rs b/src/packet/protocols/udp.rs index 993407d..21eebfa 100644 --- a/src/packet/protocols/udp.rs +++ b/src/packet/protocols/udp.rs @@ -2,6 +2,7 @@ use std::net::{IpAddr, SocketAddr}; use pnet_packet::Packet; +use super::raw::RawBytes; use crate::packet::error::PacketError; /// A UDP packet @@ -109,7 +110,7 @@ where } } -impl UdpPacket> { +impl UdpPacket { /// Construct a new UDP packet with a raw payload from bytes pub fn new_from_bytes_raw_payload( bytes: &[u8], @@ -132,7 +133,7 @@ impl UdpPacket> { Ok(Self { source: SocketAddr::new(source_address, parsed.get_source()), destination: SocketAddr::new(destination_address, parsed.get_destination()), - payload: parsed.payload().to_vec(), + payload: RawBytes(parsed.payload().to_vec()), }) } }