diff --git a/Cargo.toml b/Cargo.toml index 37458a9..86724bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,10 +38,11 @@ rtnetlink = "0.13.0" futures = "0.3.28" prometheus = "0.13.3" lazy_static = "1.4.0" +rustc-hash = "1.1.0" [[bin]] name = "protomask" -path = "src/cli/main.rs" +path = "src/main.rs" [package.metadata.deb] section = "network" diff --git a/libs/README.md b/libs/README.md new file mode 100644 index 0000000..6bfbcbc --- /dev/null +++ b/libs/README.md @@ -0,0 +1,5 @@ +# Protomask support libraries + +The development of protomask has caused the need for a few new standalone Rust libraries. + +This directory acts as a home for these support libraries until they are ready to be spun off into their own standalone repositories. diff --git a/libs/addrmap/Cargo.toml b/libs/addrmap/Cargo.toml new file mode 100644 index 0000000..f6ef74e --- /dev/null +++ b/libs/addrmap/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "addrmap" +version = "0.1.0" +authors = ["Evan Pratten "] +edition = "2021" +description = "Utilities for high-speed IP address mapping" +readme = "README.md" +homepage = "https://github.com/ewpratten/protomask" +documentation = "https://docs.rs/protomask" +repository = "https://github.com/ewpratten/protomask" +license = "GPL-3.0" +keywords = [] +categories = [] + +[dependencies] +rustc-hash = "1.1.0" diff --git a/libs/addrmap/src/ipbimap.rs b/libs/addrmap/src/ipbimap.rs new file mode 100644 index 0000000..e69de29 diff --git a/libs/addrmap/src/lib.rs b/libs/addrmap/src/lib.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/cli/cli.rs b/src/cli.rs similarity index 100% rename from src/cli/cli.rs rename to src/cli.rs diff --git a/src/cli/config.rs b/src/config.rs similarity index 100% rename from src/cli/config.rs rename to src/config.rs diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index a9d7f54..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! # Protomask library -//! -//! *Note: There is a fair chance you are looking for `src/cli/main.rs` instead of this file.* - -#![deny(clippy::pedantic)] -#![allow(clippy::module_name_repetitions)] -#![allow(clippy::missing_errors_doc)] -#![allow(clippy::missing_panics_doc)] - -pub mod metrics; -pub mod nat; -mod packet; -mod profiling; diff --git a/src/cli/main.rs b/src/main.rs similarity index 87% rename from src/cli/main.rs rename to src/main.rs index f2f2355..6a069d2 100644 --- a/src/cli/main.rs +++ b/src/main.rs @@ -2,12 +2,15 @@ use clap::Parser; use config::Config; -use logging::enable_logger; -use protomask::nat::Nat64; +use net::nat::Nat64; +use utils::logging::enable_logger; +use crate::utils::metrics::serve_metrics; + +mod utils; +mod net; mod cli; mod config; -mod logging; #[tokio::main] pub async fn main() { @@ -44,7 +47,7 @@ pub async fn main() { // Handle metrics requests if let Some(bind_addr) = config.prom_bind_addr { log::info!("Enabling metrics server on {}", bind_addr); - tokio::spawn(protomask::metrics::serve_metrics(bind_addr)); + tokio::spawn(serve_metrics(bind_addr)); } // Handle packets diff --git a/src/nat/table.rs b/src/nat/table.rs deleted file mode 100644 index e7e3693..0000000 --- a/src/nat/table.rs +++ /dev/null @@ -1,210 +0,0 @@ -use std::{ - collections::HashMap, - net::{IpAddr, Ipv4Addr, Ipv6Addr}, - time::{Duration, Instant}, -}; - -use bimap::BiHashMap; -use ipnet::Ipv4Net; - -use crate::metrics::{IPV4_POOL_RESERVED, IPV4_POOL_SIZE}; - -/// Possible errors thrown in the address reservation process -#[derive(Debug, thiserror::Error)] -pub enum TableError { - #[error("Address already reserved: {0}")] - AddressAlreadyReserved(IpAddr), - #[error("IPv4 address has no IPv6 mapping: {0}")] - NoIpv6Mapping(Ipv4Addr), - #[error("Address pool depleted")] - AddressPoolDepleted, -} - -/// A NAT address table -#[derive(Debug)] -pub struct Nat64Table { - /// All possible IPv4 addresses that can be used - ipv4_pool: Vec, - /// Current reservations - reservations: BiHashMap, - /// The timestamp of each reservation (used for pruning) - reservation_times: HashMap<(Ipv6Addr, Ipv4Addr), Option>, - /// The maximum amount of time to reserve an address pair for - reservation_timeout: Duration, -} - -impl Nat64Table { - /// Construct a new NAT64 table - /// - /// **Arguments:** - /// - `ipv4_pool`: The pool of IPv4 addresses to use in the mapping process - /// - `reservation_timeout`: The amount of time to reserve an address pair for - pub fn new(ipv4_pool: Vec, reservation_timeout: Duration) -> Self { - // Track the total pool size - let total_size: usize = ipv4_pool.iter().map(|net| net.hosts().count()).sum(); - IPV4_POOL_SIZE.set(total_size as i64); - - Self { - ipv4_pool, - reservations: BiHashMap::new(), - reservation_times: HashMap::new(), - reservation_timeout, - } - } - - /// Make a reservation for an IP address pair for eternity - pub fn add_infinite_reservation( - &mut self, - ipv6: Ipv6Addr, - ipv4: Ipv4Addr, - ) -> Result<(), TableError> { - // Check if either address is already reserved - self.prune(); - self.track_utilization(); - if self.reservations.contains_left(&ipv6) { - return Err(TableError::AddressAlreadyReserved(ipv6.into())); - } else if self.reservations.contains_right(&ipv4) { - return Err(TableError::AddressAlreadyReserved(ipv4.into())); - } - - // Add the reservation - self.reservations.insert(ipv6, ipv4); - self.reservation_times.insert((ipv6, ipv4), None); - log::info!("Added infinite reservation: {} -> {}", ipv6, ipv4); - 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 - self.prune(); - self.track_utilization(); - - // If the IPv6 address is already reserved, return the IPv4 address - if let Some(ipv4) = self.reservations.get_by_left(&ipv6) { - // Update the reservation time - self.reservation_times - .insert((ipv6, *ipv4), Some(Instant::now())); - - // Return the v4 address - return Ok(*ipv4); - } - - // Otherwise, try to assign a new IPv4 address - for ipv4_net in &self.ipv4_pool { - for ipv4 in ipv4_net.hosts() { - // Check if this address is available for use - if !self.reservations.contains_right(&ipv4) { - // Add the reservation - self.reservations.insert(ipv6, ipv4); - self.reservation_times - .insert((ipv6, ipv4), Some(Instant::now())); - log::info!("Assigned new reservation: {} -> {}", ipv6, ipv4); - return Ok(ipv4); - } - } - } - - // If we get here, we failed to find an available address - Err(TableError::AddressPoolDepleted) - } - - /// Try to find an IPv6 address for the given IPv4 address - pub fn get_reverse(&mut self, ipv4: Ipv4Addr) -> Result { - // Prune old reservations - self.prune(); - self.track_utilization(); - - // If the IPv4 address is already reserved, return the IPv6 address - if let Some(ipv6) = self.reservations.get_by_right(&ipv4) { - // Update the reservation time - self.reservation_times - .insert((*ipv6, ipv4), Some(Instant::now())); - - // Return the v6 address - return Ok(*ipv6); - } - - // Otherwise, there is no matching reservation - Err(TableError::NoIpv6Mapping(ipv4)) - } -} - -impl Nat64Table { - /// Prune old reservations - fn prune(&mut self) { - let now = Instant::now(); - - // Prune from the reservation map - self.reservations.retain(|v6, v4| { - if let Some(Some(time)) = self.reservation_times.get(&(*v6, *v4)) { - let keep = now - *time < self.reservation_timeout; - if !keep { - log::info!("Pruned reservation: {} -> {}", v6, v4); - } - keep - } else { - true - } - }); - - // Remove all times assigned to reservations that no longer exist - self.reservation_times.retain(|(v6, v4), _| { - self.reservations.contains_left(v6) && self.reservations.contains_right(v4) - }); - } - - fn track_utilization(&self) { - // Count static and dynamic in a single pass - let (total_dynamic_reservations, total_static_reservations) = self - .reservation_times - .iter() - .map(|((_v6, _v4), time)| match time { - Some(_) => (1, 0), - None => (0, 1), - }) - .fold((0, 0), |(a1, a2), (b1, b2)| (a1 + b1, a2 + b2)); - - // Track the values - IPV4_POOL_RESERVED - .with_label_values(&["dynamic"]) - .set(i64::from(total_dynamic_reservations)); - IPV4_POOL_RESERVED - .with_label_values(&["static"]) - .set(i64::from(total_static_reservations)); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_add_infinite_reservation() { - let mut table = Nat64Table::new( - vec![Ipv4Net::new(Ipv4Addr::new(192, 0, 2, 0), 24).unwrap()], - Duration::from_secs(60), - ); - - // Add a reservation - table - .add_infinite_reservation("2001:db8::1".parse().unwrap(), "192.0.2.1".parse().unwrap()) - .unwrap(); - - // Check that it worked - assert_eq!( - table - .reservations - .get_by_left(&"2001:db8::1".parse().unwrap()), - Some(&"192.0.2.1".parse().unwrap()) - ); - } -} diff --git a/src/net/mod.rs b/src/net/mod.rs new file mode 100644 index 0000000..af8e5e1 --- /dev/null +++ b/src/net/mod.rs @@ -0,0 +1,5 @@ +//! Networking logic + +// pub mod device; +pub mod nat; +pub mod packet; diff --git a/src/nat/error.rs b/src/net/nat/error.rs similarity index 87% rename from src/nat/error.rs rename to src/net/nat/error.rs index d90751a..7256de9 100644 --- a/src/nat/error.rs +++ b/src/net/nat/error.rs @@ -7,7 +7,7 @@ pub enum Nat64Error { #[error(transparent)] Io(#[from] std::io::Error), #[error(transparent)] - PacketHandling(#[from] crate::packet::error::PacketError), + PacketHandling(#[from] crate::net::packet::error::PacketError), #[error(transparent)] PacketReceive(#[from] tokio::sync::broadcast::error::RecvError), #[error(transparent)] diff --git a/src/nat/mod.rs b/src/net/nat/mod.rs similarity index 79% rename from src/nat/mod.rs rename to src/net/nat/mod.rs index 02977f5..b1f7a35 100644 --- a/src/nat/mod.rs +++ b/src/net/nat/mod.rs @@ -1,10 +1,5 @@ -use crate::{ - metrics::PACKET_COUNTER, - packet::{ - protocols::{ipv4::Ipv4Packet, ipv6::Ipv6Packet}, - xlat::ip::{translate_ipv4_to_ipv6, translate_ipv6_to_ipv4}, - }, profiling::PacketTimer, -}; + +use crate::utils::{profiling::PacketTimer, metrics::PACKET_COUNTER}; use self::{ error::Nat64Error, @@ -19,6 +14,8 @@ use std::{ }; use tokio::sync::broadcast; +use super::packet::{protocols::{ipv4::Ipv4Packet, ipv6::Ipv6Packet}, xlat::ip::{translate_ipv4_to_ipv6, translate_ipv6_to_ipv4}}; + mod error; mod table; mod utils; @@ -85,7 +82,6 @@ impl Nat64 { // 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()?; @@ -107,23 +103,20 @@ impl Nat64 { .inc(); // Spawn a task to process the packet - tokio::spawn(async move { - if let Some(output) = unwrap_log(translate_ipv4_to_ipv6( - packet, - new_source, - new_destination, - &mut timer, - )) { - tx.send(output.into()).await.unwrap(); - if should_print_profiling { - timer.log(); - } - PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc(); + if let Some(output) = unwrap_log(translate_ipv4_to_ipv6( + packet, + new_source, + new_destination, + &mut timer, + )) { + tx.send(output.into()).await.unwrap(); + if should_print_profiling { + timer.log(); } - }); + PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc(); + } } 6 => { - // Parse the packet let packet: Ipv6Packet> = packet.try_into()?; @@ -161,20 +154,18 @@ impl Nat64 { .inc(); // Spawn a task to process the packet - tokio::spawn(async move { - if let Some(output) = unwrap_log(translate_ipv6_to_ipv4( - &packet, - new_source, - new_destination, - &mut timer, - )) { - tx.send(output.into()).await.unwrap(); - if should_print_profiling { - timer.log(); - } - PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc(); + if let Some(output) = unwrap_log(translate_ipv6_to_ipv4( + &packet, + new_source, + new_destination, + &mut timer, + )) { + tx.send(output.into()).await.unwrap(); + if should_print_profiling { + timer.log(); } - }); + PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc(); + } } n => { log::warn!("Unknown IP version: {}", n); diff --git a/src/net/nat/table.rs b/src/net/nat/table.rs new file mode 100644 index 0000000..3e1d6fa --- /dev/null +++ b/src/net/nat/table.rs @@ -0,0 +1,253 @@ + +// use rustc_hash::FxHashMap; + +// #[derive(Debug, Clone, PartialEq, Eq)] +// struct IpBimap { +// v4_to_v6: FxHashMap, +// v6_to_v4: FxHashMap, +// } + +// impl IpBimap { +// /// Construct a new `IpBimap` +// pub fn new() -> Self { +// Self { +// v4_to_v6: FxHashMap::default(), +// v6_to_v4: FxHashMap::default(), +// } +// } + +// /// Insert a new mapping +// pub fn insert(&mut self, v4: u32, v6: u128) { +// self.v4_to_v6.insert(v4, v6); +// self.v6_to_v4.insert(v6, v4); +// } + +// /// Remove a mapping +// pub fn remove(&mut self, v4: u32, v6: u128) { +// self.v4_to_v6.remove(&v4); +// self.v6_to_v4.remove(&v6); +// } + +// /// Get the IPv6 address for a given IPv4 address +// pub fn get_v6(&self, v4: u32) -> Option { +// self.v4_to_v6.get(&v4).copied() +// } + +// /// Get the IPv4 address for a given IPv6 address +// pub fn get_v4(&self, v6: u128) -> Option { +// self.v6_to_v4.get(&v6).copied() +// } +// } + + +// // use std::{ +// // collections::HashMap, +// // net::{IpAddr, Ipv4Addr, Ipv6Addr}, +// // time::{Duration, Instant}, +// // }; + +// // use bimap::BiHashMap; +// // use ipnet::Ipv4Net; + +// // use crate::utils::metrics::{IPV4_POOL_SIZE, IPV4_POOL_RESERVED}; + + +// // /// Possible errors thrown in the address reservation process +// // #[derive(Debug, thiserror::Error)] +// // pub enum TableError { +// // #[error("Address already reserved: {0}")] +// // AddressAlreadyReserved(IpAddr), +// // #[error("IPv4 address has no IPv6 mapping: {0}")] +// // NoIpv6Mapping(Ipv4Addr), +// // #[error("Address pool depleted")] +// // AddressPoolDepleted, +// // } + +// // /// A NAT address table +// // #[derive(Debug)] +// // pub struct Nat64Table { +// // /// All possible IPv4 addresses that can be used +// // ipv4_pool: Vec, +// // /// Current reservations +// // reservations: BiHashMap, +// // /// The timestamp of each reservation (used for pruning) +// // reservation_times: HashMap<(Ipv6Addr, Ipv4Addr), Option>, +// // /// The maximum amount of time to reserve an address pair for +// // reservation_timeout: Duration, +// // } + +// // impl Nat64Table { +// // /// Construct a new NAT64 table +// // /// +// // /// **Arguments:** +// // /// - `ipv4_pool`: The pool of IPv4 addresses to use in the mapping process +// // /// - `reservation_timeout`: The amount of time to reserve an address pair for +// // pub fn new(ipv4_pool: Vec, reservation_timeout: Duration) -> Self { +// // // Track the total pool size +// // let total_size: usize = ipv4_pool.iter().map(|net| net.hosts().count()).sum(); +// // IPV4_POOL_SIZE.set(total_size as i64); + +// // Self { +// // ipv4_pool, +// // reservations: BiHashMap::new(), +// // reservation_times: HashMap::new(), +// // reservation_timeout, +// // } +// // } + +// // /// Make a reservation for an IP address pair for eternity +// // pub fn add_infinite_reservation( +// // &mut self, +// // ipv6: Ipv6Addr, +// // ipv4: Ipv4Addr, +// // ) -> Result<(), TableError> { +// // // Check if either address is already reserved +// // self.prune(); +// // self.track_utilization(); +// // if self.reservations.contains_left(&ipv6) { +// // return Err(TableError::AddressAlreadyReserved(ipv6.into())); +// // } else if self.reservations.contains_right(&ipv4) { +// // return Err(TableError::AddressAlreadyReserved(ipv4.into())); +// // } + +// // // Add the reservation +// // self.reservations.insert(ipv6, ipv4); +// // self.reservation_times.insert((ipv6, ipv4), None); +// // log::info!("Added infinite reservation: {} -> {}", ipv6, ipv4); +// // 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 +// // self.prune(); +// // self.track_utilization(); + +// // // If the IPv6 address is already reserved, return the IPv4 address +// // if let Some(ipv4) = self.reservations.get_by_left(&ipv6) { +// // // Update the reservation time +// // self.reservation_times +// // .insert((ipv6, *ipv4), Some(Instant::now())); + +// // // Return the v4 address +// // return Ok(*ipv4); +// // } + +// // // Otherwise, try to assign a new IPv4 address +// // for ipv4_net in &self.ipv4_pool { +// // for ipv4 in ipv4_net.hosts() { +// // // Check if this address is available for use +// // if !self.reservations.contains_right(&ipv4) { +// // // Add the reservation +// // self.reservations.insert(ipv6, ipv4); +// // self.reservation_times +// // .insert((ipv6, ipv4), Some(Instant::now())); +// // log::info!("Assigned new reservation: {} -> {}", ipv6, ipv4); +// // return Ok(ipv4); +// // } +// // } +// // } + +// // // If we get here, we failed to find an available address +// // Err(TableError::AddressPoolDepleted) +// // } + +// // /// Try to find an IPv6 address for the given IPv4 address +// // pub fn get_reverse(&mut self, ipv4: Ipv4Addr) -> Result { +// // // Prune old reservations +// // self.prune(); +// // self.track_utilization(); + +// // // If the IPv4 address is already reserved, return the IPv6 address +// // if let Some(ipv6) = self.reservations.get_by_right(&ipv4) { +// // // Update the reservation time +// // self.reservation_times +// // .insert((*ipv6, ipv4), Some(Instant::now())); + +// // // Return the v6 address +// // return Ok(*ipv6); +// // } + +// // // Otherwise, there is no matching reservation +// // Err(TableError::NoIpv6Mapping(ipv4)) +// // } +// // } + +// // impl Nat64Table { +// // /// Prune old reservations +// // fn prune(&mut self) { +// // let now = Instant::now(); + +// // // Prune from the reservation map +// // self.reservations.retain(|v6, v4| { +// // if let Some(Some(time)) = self.reservation_times.get(&(*v6, *v4)) { +// // let keep = now - *time < self.reservation_timeout; +// // if !keep { +// // log::info!("Pruned reservation: {} -> {}", v6, v4); +// // } +// // keep +// // } else { +// // true +// // } +// // }); + +// // // Remove all times assigned to reservations that no longer exist +// // self.reservation_times.retain(|(v6, v4), _| { +// // self.reservations.contains_left(v6) && self.reservations.contains_right(v4) +// // }); +// // } + +// // fn track_utilization(&self) { +// // // Count static and dynamic in a single pass +// // let (total_dynamic_reservations, total_static_reservations) = self +// // .reservation_times +// // .iter() +// // .map(|((_v6, _v4), time)| match time { +// // Some(_) => (1, 0), +// // None => (0, 1), +// // }) +// // .fold((0, 0), |(a1, a2), (b1, b2)| (a1 + b1, a2 + b2)); + +// // // Track the values +// // IPV4_POOL_RESERVED +// // .with_label_values(&["dynamic"]) +// // .set(i64::from(total_dynamic_reservations)); +// // IPV4_POOL_RESERVED +// // .with_label_values(&["static"]) +// // .set(i64::from(total_static_reservations)); +// // } +// // } + +// // #[cfg(test)] +// // mod tests { +// // use super::*; + +// // #[test] +// // fn test_add_infinite_reservation() { +// // let mut table = Nat64Table::new( +// // vec![Ipv4Net::new(Ipv4Addr::new(192, 0, 2, 0), 24).unwrap()], +// // Duration::from_secs(60), +// // ); + +// // // Add a reservation +// // table +// // .add_infinite_reservation("2001:db8::1".parse().unwrap(), "192.0.2.1".parse().unwrap()) +// // .unwrap(); + +// // // Check that it worked +// // assert_eq!( +// // table +// // .reservations +// // .get_by_left(&"2001:db8::1".parse().unwrap()), +// // Some(&"192.0.2.1".parse().unwrap()) +// // ); +// // } +// // } diff --git a/src/nat/utils.rs b/src/net/nat/utils.rs similarity index 97% rename from src/nat/utils.rs rename to src/net/nat/utils.rs index 44d1f18..fdfba15 100644 --- a/src/nat/utils.rs +++ b/src/net/nat/utils.rs @@ -2,7 +2,7 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use ipnet::Ipv6Net; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; /// Embed an IPv4 address in an IPv6 prefix pub fn embed_address(ipv4_address: Ipv4Addr, ipv6_prefix: Ipv6Net) -> Ipv6Addr { diff --git a/src/packet/error.rs b/src/net/packet/error.rs similarity index 100% rename from src/packet/error.rs rename to src/net/packet/error.rs diff --git a/src/net/packet/mod.rs b/src/net/packet/mod.rs new file mode 100644 index 0000000..ebcff2b --- /dev/null +++ b/src/net/packet/mod.rs @@ -0,0 +1,5 @@ +//! Tools for efficiently creating and modifying packets + +pub mod error; +pub mod protocols; +pub mod xlat; diff --git a/src/packet/protocols/icmp.rs b/src/net/packet/protocols/icmp.rs similarity index 98% rename from src/packet/protocols/icmp.rs rename to src/net/packet/protocols/icmp.rs index 53e4a2a..ec146c6 100644 --- a/src/packet/protocols/icmp.rs +++ b/src/net/packet/protocols/icmp.rs @@ -3,7 +3,7 @@ use pnet_packet::{ Packet, }; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct IcmpPacket { diff --git a/src/packet/protocols/icmpv6.rs b/src/net/packet/protocols/icmpv6.rs similarity index 98% rename from src/packet/protocols/icmpv6.rs rename to src/net/packet/protocols/icmpv6.rs index d320e93..df8b788 100644 --- a/src/packet/protocols/icmpv6.rs +++ b/src/net/packet/protocols/icmpv6.rs @@ -5,7 +5,7 @@ use pnet_packet::{ Packet, }; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; use super::raw::RawBytes; diff --git a/src/packet/protocols/ipv4.rs b/src/net/packet/protocols/ipv4.rs similarity index 98% rename from src/packet/protocols/ipv4.rs rename to src/net/packet/protocols/ipv4.rs index 6b17f6b..eef63b4 100644 --- a/src/packet/protocols/ipv4.rs +++ b/src/net/packet/protocols/ipv4.rs @@ -6,7 +6,7 @@ use pnet_packet::{ Packet, }; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; #[derive(Debug, Clone)] pub struct Ipv4Packet { diff --git a/src/packet/protocols/ipv6.rs b/src/net/packet/protocols/ipv6.rs similarity index 98% rename from src/packet/protocols/ipv6.rs rename to src/net/packet/protocols/ipv6.rs index bd89377..406ff32 100644 --- a/src/packet/protocols/ipv6.rs +++ b/src/net/packet/protocols/ipv6.rs @@ -2,7 +2,7 @@ use std::net::Ipv6Addr; use pnet_packet::{ip::IpNextHeaderProtocol, Packet}; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Ipv6Packet { diff --git a/src/packet/protocols/mod.rs b/src/net/packet/protocols/mod.rs similarity index 60% rename from src/packet/protocols/mod.rs rename to src/net/packet/protocols/mod.rs index ae58976..7553480 100644 --- a/src/packet/protocols/mod.rs +++ b/src/net/packet/protocols/mod.rs @@ -1,3 +1,5 @@ +//! Definitions for each type of packet `protomask` can handle + pub mod icmp; pub mod icmpv6; pub mod ipv4; diff --git a/src/packet/protocols/raw.rs b/src/net/packet/protocols/raw.rs similarity index 88% rename from src/packet/protocols/raw.rs rename to src/net/packet/protocols/raw.rs index 91e10e7..7354499 100644 --- a/src/packet/protocols/raw.rs +++ b/src/net/packet/protocols/raw.rs @@ -1,4 +1,4 @@ -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RawBytes(pub Vec); diff --git a/src/packet/protocols/tcp.rs b/src/net/packet/protocols/tcp.rs similarity index 99% rename from src/packet/protocols/tcp.rs rename to src/net/packet/protocols/tcp.rs index d1623e5..19fe209 100644 --- a/src/packet/protocols/tcp.rs +++ b/src/net/packet/protocols/tcp.rs @@ -6,7 +6,7 @@ use pnet_packet::{ }; use super::raw::RawBytes; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; /// A TCP packet #[derive(Debug, Clone)] diff --git a/src/packet/protocols/udp.rs b/src/net/packet/protocols/udp.rs similarity index 99% rename from src/packet/protocols/udp.rs rename to src/net/packet/protocols/udp.rs index 98b73dd..f9099c0 100644 --- a/src/packet/protocols/udp.rs +++ b/src/net/packet/protocols/udp.rs @@ -3,7 +3,7 @@ use std::net::{IpAddr, SocketAddr}; use pnet_packet::Packet; use super::raw::RawBytes; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; /// A UDP packet #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/packet/xlat/icmp/mod.rs b/src/net/packet/xlat/icmp/mod.rs similarity index 94% rename from src/packet/xlat/icmp/mod.rs rename to src/net/packet/xlat/icmp/mod.rs index dd40034..f4abdc3 100644 --- a/src/packet/xlat/icmp/mod.rs +++ b/src/net/packet/xlat/icmp/mod.rs @@ -4,13 +4,8 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use pnet_packet::{icmp::IcmpTypes, icmpv6::Icmpv6Types}; -use crate::{ - metrics::ICMP_COUNTER, - packet::{ - error::PacketError, - protocols::{icmp::IcmpPacket, icmpv6::Icmpv6Packet, raw::RawBytes}, - }, profiling::{PacketTimer, TimerScope}, -}; + +use crate::{utils::{profiling::{TimerScope, PacketTimer}, metrics::ICMP_COUNTER}, net::packet::{protocols::{raw::RawBytes, icmpv6::Icmpv6Packet, icmp::IcmpPacket}, error::PacketError}}; use super::ip::{translate_ipv4_to_ipv6, translate_ipv6_to_ipv4}; diff --git a/src/packet/xlat/icmp/type_code.rs b/src/net/packet/xlat/icmp/type_code.rs similarity index 98% rename from src/packet/xlat/icmp/type_code.rs rename to src/net/packet/xlat/icmp/type_code.rs index 8aead6c..97208ee 100644 --- a/src/packet/xlat/icmp/type_code.rs +++ b/src/net/packet/xlat/icmp/type_code.rs @@ -7,7 +7,7 @@ use pnet_packet::{ icmpv6::{Icmpv6Code, Icmpv6Type, Icmpv6Types}, }; -use crate::packet::error::PacketError; +use crate::net::packet::error::PacketError; /// Best effort translation from an ICMP type and code to an ICMPv6 type and code #[allow(clippy::deprecated_cfg_attr)] diff --git a/src/packet/xlat/ip.rs b/src/net/packet/xlat/ip.rs similarity index 96% rename from src/packet/xlat/ip.rs rename to src/net/packet/xlat/ip.rs index be4040f..894d5e2 100644 --- a/src/packet/xlat/ip.rs +++ b/src/net/packet/xlat/ip.rs @@ -3,11 +3,10 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use pnet_packet::ip::IpNextHeaderProtocols; use crate::{ - packet::protocols::{icmp::IcmpPacket, tcp::TcpPacket, udp::UdpPacket}, - packet::{ + net::packet::{ error::PacketError, - protocols::{icmpv6::Icmpv6Packet, ipv4::Ipv4Packet, ipv6::Ipv6Packet, raw::RawBytes}, - }, profiling::{PacketTimer, TimerScope}, + protocols::{icmpv6::Icmpv6Packet, ipv4::Ipv4Packet, ipv6::Ipv6Packet, raw::RawBytes, icmp::IcmpPacket, udp::UdpPacket, tcp::TcpPacket}, + }, utils::profiling::{TimerScope, PacketTimer}, }; use super::{ diff --git a/src/packet/xlat/mod.rs b/src/net/packet/xlat/mod.rs similarity index 100% rename from src/packet/xlat/mod.rs rename to src/net/packet/xlat/mod.rs diff --git a/src/packet/xlat/tcp.rs b/src/net/packet/xlat/tcp.rs similarity index 94% rename from src/packet/xlat/tcp.rs rename to src/net/packet/xlat/tcp.rs index 5a21bc6..f2c7965 100644 --- a/src/packet/xlat/tcp.rs +++ b/src/net/packet/xlat/tcp.rs @@ -1,16 +1,19 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; -use crate::{packet::{ - error::PacketError, - protocols::{raw::RawBytes, tcp::TcpPacket}, -}, profiling::{PacketTimer, TimerScope}}; +use crate::{ + net::packet::{ + error::PacketError, + protocols::{raw::RawBytes, tcp::TcpPacket}, + }, + utils::profiling::{PacketTimer, TimerScope}, +}; /// Translates an IPv4 TCP packet to an IPv6 TCP packet pub fn translate_tcp4_to_tcp6( input: TcpPacket, new_source_addr: Ipv6Addr, new_destination_addr: Ipv6Addr, - timer: &mut PacketTimer + timer: &mut PacketTimer, ) -> Result, PacketError> { // Build the packet timer.start(TimerScope::Tcp); @@ -34,7 +37,7 @@ pub fn translate_tcp6_to_tcp4( input: TcpPacket, new_source_addr: Ipv4Addr, new_destination_addr: Ipv4Addr, - timer: &mut PacketTimer + timer: &mut PacketTimer, ) -> Result, PacketError> { // Build the packet timer.start(TimerScope::Tcp); diff --git a/src/packet/xlat/udp.rs b/src/net/packet/xlat/udp.rs similarity index 96% rename from src/packet/xlat/udp.rs rename to src/net/packet/xlat/udp.rs index 0498696..6c4af1a 100644 --- a/src/packet/xlat/udp.rs +++ b/src/net/packet/xlat/udp.rs @@ -1,11 +1,11 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use crate::{ - packet::{ + net::packet::{ error::PacketError, protocols::{raw::RawBytes, udp::UdpPacket}, }, - profiling::{PacketTimer, TimerScope}, + utils::profiling::{PacketTimer, TimerScope}, }; /// Translates an IPv4 UDP packet to an IPv6 UDP packet @@ -47,7 +47,7 @@ pub fn translate_udp6_to_udp4( #[cfg(test)] mod tests { use super::*; - use crate::packet::protocols::udp::UdpPacket; + use crate::net::packet::protocols::udp::UdpPacket; #[test] fn test_translate_udp4_to_udp6() { diff --git a/src/packet/mod.rs b/src/packet/mod.rs deleted file mode 100644 index a40cbd5..0000000 --- a/src/packet/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Custom packet modification utilities -//! -//! pnet isn't quite what we need for this project, so the contents of this module wrap it to make it easier to use. - -pub mod error; -pub mod protocols; -pub mod xlat; diff --git a/src/cli/logging.rs b/src/utils/logging.rs similarity index 100% rename from src/cli/logging.rs rename to src/utils/logging.rs diff --git a/src/metrics/http.rs b/src/utils/metrics/http.rs similarity index 100% rename from src/metrics/http.rs rename to src/utils/metrics/http.rs diff --git a/src/metrics/metrics.rs b/src/utils/metrics/metrics.rs similarity index 100% rename from src/metrics/metrics.rs rename to src/utils/metrics/metrics.rs diff --git a/src/metrics/mod.rs b/src/utils/metrics/mod.rs similarity index 100% rename from src/metrics/mod.rs rename to src/utils/metrics/mod.rs diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..6fd9ac1 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,3 @@ +pub mod logging; +pub mod profiling; +pub mod metrics; \ No newline at end of file diff --git a/src/profiling.rs b/src/utils/profiling.rs similarity index 95% rename from src/profiling.rs rename to src/utils/profiling.rs index d76c3de..fd301b5 100644 --- a/src/profiling.rs +++ b/src/utils/profiling.rs @@ -85,7 +85,7 @@ impl PacketTimer { pub fn log(&self) { log::trace!( - "[Timer report] proto: {}, total: {:05}µs, ipv4_to_ipv6: {:05}µs, ipv6_to_ipv4: {:05}µs, icmp_to_icmpv6: {:05}µs, icmpv6_to_icmp: {:05}µs, udp: {:05}µs, tcp: {:05}µs", + "[Timer report] proto: {}, total: {:05}µs, ipv4_to_ipv6: {:05}µs, ipv6_to_ipv4: {:05}µs, icmp_to_icmpv6: {:05}µs, icmpv6_to_icmp: {:05}µs, udp: {:05}ns, tcp: {:05}ns", self.protocol, self.creation_time.elapsed().as_micros(), self.states.get(&TimerScope::Ipv4ToIpv6).map(|val| match val { @@ -105,11 +105,11 @@ impl PacketTimer { _=>0 }).unwrap_or(0), self.states.get(&TimerScope::Udp).map(|val| match val { - TimerState::Ended(duration, _) => duration.as_micros(), + TimerState::Ended(duration, _) => duration.as_nanos(), _=>0 }).unwrap_or(0), self.states.get(&TimerScope::Tcp).map(|val| match val { - TimerState::Ended(duration, _) => duration.as_micros(), + TimerState::Ended(duration, _) => duration.as_nanos(), _=>0 }).unwrap_or(0), );