1

Perform reorg into single bin

This commit is contained in:
Evan Pratten 2023-07-28 12:58:36 -04:00
parent c795ed15fc
commit 2ed63e526a
38 changed files with 354 additions and 303 deletions

View File

@ -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"

5
libs/README.md Normal file
View File

@ -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.

16
libs/addrmap/Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "addrmap"
version = "0.1.0"
authors = ["Evan Pratten <ewpratten@gmail.com>"]
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"

View File

0
libs/addrmap/src/lib.rs Normal file
View File

View File

@ -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;

View File

@ -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

View File

@ -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<Ipv4Net>,
/// Current reservations
reservations: BiHashMap<Ipv6Addr, Ipv4Addr>,
/// The timestamp of each reservation (used for pruning)
reservation_times: HashMap<(Ipv6Addr, Ipv4Addr), Option<Instant>>,
/// 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<Ipv4Net>, 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<Ipv4Addr, TableError> {
// 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<Ipv6Addr, TableError> {
// 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())
);
}
}

5
src/net/mod.rs Normal file
View File

@ -0,0 +1,5 @@
//! Networking logic
// pub mod device;
pub mod nat;
pub mod packet;

View File

@ -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)]

View File

@ -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<Vec<u8>> = 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<Vec<u8>> = 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);

253
src/net/nat/table.rs Normal file
View File

@ -0,0 +1,253 @@
// use rustc_hash::FxHashMap;
// #[derive(Debug, Clone, PartialEq, Eq)]
// struct IpBimap {
// v4_to_v6: FxHashMap<u32, u128>,
// v6_to_v4: FxHashMap<u128, u32>,
// }
// 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<u128> {
// self.v4_to_v6.get(&v4).copied()
// }
// /// Get the IPv4 address for a given IPv6 address
// pub fn get_v4(&self, v6: u128) -> Option<u32> {
// 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<Ipv4Net>,
// // /// Current reservations
// // reservations: BiHashMap<Ipv6Addr, Ipv4Addr>,
// // /// The timestamp of each reservation (used for pruning)
// // reservation_times: HashMap<(Ipv6Addr, Ipv4Addr), Option<Instant>>,
// // /// 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<Ipv4Net>, 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<Ipv4Addr, TableError> {
// // // 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<Ipv6Addr, TableError> {
// // // 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())
// // );
// // }
// // }

View File

@ -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 {

5
src/net/packet/mod.rs Normal file
View File

@ -0,0 +1,5 @@
//! Tools for efficiently creating and modifying packets
pub mod error;
pub mod protocols;
pub mod xlat;

View File

@ -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<T> {

View File

@ -5,7 +5,7 @@ use pnet_packet::{
Packet,
};
use crate::packet::error::PacketError;
use crate::net::packet::error::PacketError;
use super::raw::RawBytes;

View File

@ -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<T> {

View File

@ -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<T> {

View File

@ -1,3 +1,5 @@
//! Definitions for each type of packet `protomask` can handle
pub mod icmp;
pub mod icmpv6;
pub mod ipv4;

View File

@ -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<u8>);

View File

@ -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)]

View File

@ -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)]

View File

@ -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};

View File

@ -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)]

View File

@ -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::{

View File

@ -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<RawBytes>,
new_source_addr: Ipv6Addr,
new_destination_addr: Ipv6Addr,
timer: &mut PacketTimer
timer: &mut PacketTimer,
) -> Result<TcpPacket<RawBytes>, PacketError> {
// Build the packet
timer.start(TimerScope::Tcp);
@ -34,7 +37,7 @@ pub fn translate_tcp6_to_tcp4(
input: TcpPacket<RawBytes>,
new_source_addr: Ipv4Addr,
new_destination_addr: Ipv4Addr,
timer: &mut PacketTimer
timer: &mut PacketTimer,
) -> Result<TcpPacket<RawBytes>, PacketError> {
// Build the packet
timer.start(TimerScope::Tcp);

View File

@ -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() {

View File

@ -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;

3
src/utils/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod logging;
pub mod profiling;
pub mod metrics;

View File

@ -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),
);