wip
This commit is contained in:
parent
33a2dd685f
commit
bb9b41861b
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[build]
|
||||||
|
rustflags = ["--cfg", "tokio_unstable"]
|
37
Cargo.toml
37
Cargo.toml
@ -12,20 +12,26 @@ license = "GPL-3.0"
|
|||||||
keywords = []
|
keywords = []
|
||||||
categories = []
|
categories = []
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[features]
|
||||||
|
default = []
|
||||||
|
profiling = ["profiling/profile-with-puffin", "puffin_http", "puffin"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
protomask-tun = { path = "protomask-tun", version = "0.1.0" }
|
|
||||||
tokio = { version = "1.29.1", features = [
|
tokio = { version = "1.29.1", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
# "process",
|
"sync",
|
||||||
"sync"
|
"tracing",
|
||||||
] }
|
] }
|
||||||
clap = { version = "4.3.11", features = ["derive"] }
|
clap = { version = "4.3.11", features = ["derive"] }
|
||||||
serde = { version = "1.0.171", features = ["derive"] }
|
serde = { version = "1.0.171", features = ["derive"] }
|
||||||
ipnet = { version = "2.8.0", features = ["serde"] }
|
ipnet = { version = "2.8.0", features = ["serde"] }
|
||||||
hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
|
hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
|
||||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||||
|
puffin_http = { version = "0.13.0", optional = true }
|
||||||
|
puffin = { version = "0.16.0", optional = true }
|
||||||
|
profiling = "1.0.8"
|
||||||
|
tracing = "0.1.37"
|
||||||
toml = "0.7.6"
|
toml = "0.7.6"
|
||||||
log = "0.4.19"
|
log = "0.4.19"
|
||||||
fern = "0.6.2"
|
fern = "0.6.2"
|
||||||
@ -41,16 +47,29 @@ lazy_static = "1.4.0"
|
|||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "protomask"
|
name = "protomask"
|
||||||
path = "src/cli/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
section = "network"
|
section = "network"
|
||||||
assets = [
|
assets = [
|
||||||
["target/release/protomask", "/usr/local/bin/protomask", "755"],
|
[
|
||||||
["./protomask.toml", "/etc/protomask.toml", "644"],
|
"target/release/protomask",
|
||||||
["README.md", "usr/share/doc/protomask/README.md", "644"]
|
"/usr/local/bin/protomask",
|
||||||
|
"755",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"./protomask.toml",
|
||||||
|
"/etc/protomask.toml",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"README.md",
|
||||||
|
"usr/share/doc/protomask/README.md",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
]
|
]
|
||||||
conf-files = ["/etc/protomask.toml"]
|
conf-files = ["/etc/protomask.toml"]
|
||||||
depends = []
|
depends = []
|
||||||
maintainer-scripts = "./debian/"
|
maintainer-scripts = "./debian/"
|
||||||
systemd-units = { enable = false }
|
systemd-units = { enable = false }
|
||||||
|
5
Makefile
5
Makefile
@ -1,5 +1,5 @@
|
|||||||
# All sources used to build the protomask binary
|
# All sources used to build the protomask binary
|
||||||
SRC = Cargo.toml $(shell find src/ -type f -name '*.rs') $(shell find protomask-tun/src/ -type f -name '*.rs')
|
SRC = Cargo.toml $(shell find src/ -type f -name '*.rs')
|
||||||
|
|
||||||
# Used to auto-version things
|
# Used to auto-version things
|
||||||
CRATE_VERSION = $(shell sed -n -r "s/^version = \"([0-9\.]+)\"/\1/p" Cargo.toml)
|
CRATE_VERSION = $(shell sed -n -r "s/^version = \"([0-9\.]+)\"/\1/p" Cargo.toml)
|
||||||
@ -7,6 +7,9 @@ CRATE_VERSION = $(shell sed -n -r "s/^version = \"([0-9\.]+)\"/\1/p" Cargo.toml)
|
|||||||
target/x86_64-unknown-linux-musl/release/protomask: $(SRC)
|
target/x86_64-unknown-linux-musl/release/protomask: $(SRC)
|
||||||
cross build --target x86_64-unknown-linux-musl --release
|
cross build --target x86_64-unknown-linux-musl --release
|
||||||
|
|
||||||
|
target/x86_64-unknown-linux-musl/debug/protomask: $(SRC)
|
||||||
|
cross build --target x86_64-unknown-linux-musl --features profiling
|
||||||
|
|
||||||
target/aarch64-unknown-linux-musl/release/protomask: $(SRC)
|
target/aarch64-unknown-linux-musl/release/protomask: $(SRC)
|
||||||
cross build --target aarch64-unknown-linux-musl --release
|
cross build --target aarch64-unknown-linux-musl --release
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "protomask-tun"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Evan Pratten <ewpratten@gmail.com>"]
|
|
||||||
edition = "2021"
|
|
||||||
description = "An async interface to Linux TUN devices"
|
|
||||||
readme = "README.md"
|
|
||||||
homepage = "https://github.com/ewpratten/protomask/protomask-tun"
|
|
||||||
documentation = "https://docs.rs/protomask-tun"
|
|
||||||
repository = "https://github.com/ewpratten/protomask"
|
|
||||||
license = "GPL-3.0"
|
|
||||||
keywords = []
|
|
||||||
categories = []
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
[dependencies]
|
|
||||||
tokio = { version = "1.29.1", features = ["sync", "rt"] }
|
|
||||||
log = "0.4.19"
|
|
||||||
thiserror = "1.0.43"
|
|
||||||
tun-tap = "0.1.3"
|
|
||||||
rtnetlink = "0.13.0"
|
|
||||||
futures = "0.3.28"
|
|
||||||
ipnet = "^2.8.0"
|
|
@ -1,3 +0,0 @@
|
|||||||
# protomask-tun
|
|
||||||
|
|
||||||
An async interface to Linux TUN devices. Support library for `protomask`.
|
|
@ -1,5 +0,0 @@
|
|||||||
mod error;
|
|
||||||
mod tun;
|
|
||||||
|
|
||||||
pub use error::{Error, Result};
|
|
||||||
pub use tun::TunDevice;
|
|
5
src/cli/mod.rs
Normal file
5
src/cli/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod cli;
|
||||||
|
pub mod config;
|
||||||
|
pub mod logging;
|
||||||
|
|
||||||
|
pub use cli::Args;
|
12
src/lib.rs
12
src/lib.rs
@ -1,12 +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;
|
|
@ -1,16 +1,29 @@
|
|||||||
//! This is the entrypoint for `protomask` from the command line.
|
//! The `protomask` application entrypoint
|
||||||
|
|
||||||
|
#![deny(clippy::pedantic)]
|
||||||
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
#![allow(clippy::missing_errors_doc)]
|
||||||
|
#![allow(clippy::missing_panics_doc)]
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use config::Config;
|
use cli::{config::Config, logging::enable_logger};
|
||||||
use logging::enable_logger;
|
use nat::Nat64;
|
||||||
use protomask::nat::Nat64;
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod config;
|
mod metrics;
|
||||||
mod logging;
|
mod nat;
|
||||||
|
mod packet;
|
||||||
|
mod tun;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn main() {
|
pub async fn main() {
|
||||||
|
// Enable profiling server if we are building with `--features profiling`
|
||||||
|
#[cfg(feature = "profiling")]
|
||||||
|
let _puffin_server =
|
||||||
|
puffin_http::Server::new(&format!("[::]:{}", puffin_http::DEFAULT_PORT)).unwrap();
|
||||||
|
#[cfg(feature = "profiling")]
|
||||||
|
puffin::set_scopes_on(true);
|
||||||
|
|
||||||
// Parse CLI args
|
// Parse CLI args
|
||||||
let args = cli::Args::parse();
|
let args = cli::Args::parse();
|
||||||
|
|
||||||
@ -44,7 +57,7 @@ pub async fn main() {
|
|||||||
// Handle metrics requests
|
// Handle metrics requests
|
||||||
if let Some(bind_addr) = config.prom_bind_addr {
|
if let Some(bind_addr) = config.prom_bind_addr {
|
||||||
log::info!("Enabling metrics server on {}", bind_addr);
|
log::info!("Enabling metrics server on {}", bind_addr);
|
||||||
tokio::spawn(protomask::metrics::serve_metrics(bind_addr));
|
tokio::spawn(metrics::serve_metrics(bind_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle packets
|
// Handle packets
|
@ -3,7 +3,7 @@ pub enum Nat64Error {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Table(#[from] super::table::TableError),
|
Table(#[from] super::table::TableError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Tun(#[from] protomask_tun::Error),
|
Tun(#[from] crate::tun::TunError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
@ -12,7 +12,7 @@ use self::{
|
|||||||
utils::{embed_address, extract_address, unwrap_log},
|
utils::{embed_address, extract_address, unwrap_log},
|
||||||
};
|
};
|
||||||
use ipnet::{Ipv4Net, Ipv6Net};
|
use ipnet::{Ipv4Net, Ipv6Net};
|
||||||
use protomask_tun::TunDevice;
|
use crate::tun::TunDevice;
|
||||||
use std::{
|
use std::{
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@ -68,6 +68,8 @@ impl Nat64 {
|
|||||||
|
|
||||||
// Process packets in a loop
|
// Process packets in a loop
|
||||||
loop {
|
loop {
|
||||||
|
profiling::finish_frame!();
|
||||||
|
|
||||||
// Try to read a packet
|
// Try to read a packet
|
||||||
match rx.recv().await {
|
match rx.recv().await {
|
||||||
Ok(packet) => {
|
Ok(packet) => {
|
||||||
@ -98,7 +100,7 @@ impl Nat64 {
|
|||||||
.inc();
|
.inc();
|
||||||
|
|
||||||
// Spawn a task to process the packet
|
// Spawn a task to process the packet
|
||||||
tokio::spawn(async move {
|
// tokio::spawn(async move {
|
||||||
if let Some(output) = unwrap_log(translate_ipv4_to_ipv6(
|
if let Some(output) = unwrap_log(translate_ipv4_to_ipv6(
|
||||||
packet,
|
packet,
|
||||||
new_source,
|
new_source,
|
||||||
@ -107,7 +109,7 @@ impl Nat64 {
|
|||||||
tx.send(output.into()).await.unwrap();
|
tx.send(output.into()).await.unwrap();
|
||||||
PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc();
|
PACKET_COUNTER.with_label_values(&["ipv6", "sent"]).inc();
|
||||||
}
|
}
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
6 => {
|
6 => {
|
||||||
// Parse the packet
|
// Parse the packet
|
||||||
@ -147,7 +149,7 @@ impl Nat64 {
|
|||||||
.inc();
|
.inc();
|
||||||
|
|
||||||
// Spawn a task to process the packet
|
// Spawn a task to process the packet
|
||||||
tokio::spawn(async move {
|
// tokio::spawn(async move {
|
||||||
if let Some(output) = unwrap_log(translate_ipv6_to_ipv4(
|
if let Some(output) = unwrap_log(translate_ipv6_to_ipv4(
|
||||||
&packet,
|
&packet,
|
||||||
new_source,
|
new_source,
|
||||||
@ -156,7 +158,7 @@ impl Nat64 {
|
|||||||
tx.send(output.into()).await.unwrap();
|
tx.send(output.into()).await.unwrap();
|
||||||
PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc();
|
PACKET_COUNTER.with_label_values(&["ipv4", "sent"]).inc();
|
||||||
}
|
}
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
n => {
|
n => {
|
||||||
log::warn!("Unknown IP version: {}", n);
|
log::warn!("Unknown IP version: {}", n);
|
||||||
|
@ -53,6 +53,7 @@ impl Nat64Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Make a reservation for an IP address pair for eternity
|
/// Make a reservation for an IP address pair for eternity
|
||||||
|
#[profiling::function]
|
||||||
pub fn add_infinite_reservation(
|
pub fn add_infinite_reservation(
|
||||||
&mut self,
|
&mut self,
|
||||||
ipv6: Ipv6Addr,
|
ipv6: Ipv6Addr,
|
||||||
@ -75,6 +76,7 @@ impl Nat64Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a given address exists in the table
|
/// Check if a given address exists in the table
|
||||||
|
#[profiling::function]
|
||||||
pub fn contains(&self, address: &IpAddr) -> bool {
|
pub fn contains(&self, address: &IpAddr) -> bool {
|
||||||
match address {
|
match address {
|
||||||
IpAddr::V4(ipv4) => self.reservations.contains_right(ipv4),
|
IpAddr::V4(ipv4) => self.reservations.contains_right(ipv4),
|
||||||
@ -83,6 +85,7 @@ impl Nat64Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get or assign an IPv4 address for the given IPv6 address
|
/// Get or assign an IPv4 address for the given IPv6 address
|
||||||
|
#[profiling::function]
|
||||||
pub fn get_or_assign_ipv4(&mut self, ipv6: Ipv6Addr) -> Result<Ipv4Addr, TableError> {
|
pub fn get_or_assign_ipv4(&mut self, ipv6: Ipv6Addr) -> Result<Ipv4Addr, TableError> {
|
||||||
// Prune old reservations
|
// Prune old reservations
|
||||||
self.prune();
|
self.prune();
|
||||||
@ -118,6 +121,7 @@ impl Nat64Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Try to find an IPv6 address for the given IPv4 address
|
/// Try to find an IPv6 address for the given IPv4 address
|
||||||
|
#[profiling::function]
|
||||||
pub fn get_reverse(&mut self, ipv4: Ipv4Addr) -> Result<Ipv6Addr, TableError> {
|
pub fn get_reverse(&mut self, ipv4: Ipv4Addr) -> Result<Ipv6Addr, TableError> {
|
||||||
// Prune old reservations
|
// Prune old reservations
|
||||||
self.prune();
|
self.prune();
|
||||||
@ -140,6 +144,7 @@ impl Nat64Table {
|
|||||||
|
|
||||||
impl Nat64Table {
|
impl Nat64Table {
|
||||||
/// Prune old reservations
|
/// Prune old reservations
|
||||||
|
#[profiling::function]
|
||||||
fn prune(&mut self) {
|
fn prune(&mut self) {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
@ -162,6 +167,7 @@ impl Nat64Table {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[profiling::function]
|
||||||
fn track_utilization(&self) {
|
fn track_utilization(&self) {
|
||||||
// Count static and dynamic in a single pass
|
// Count static and dynamic in a single pass
|
||||||
let (total_dynamic_reservations, total_static_reservations) = self
|
let (total_dynamic_reservations, total_static_reservations) = self
|
||||||
|
@ -17,6 +17,7 @@ use super::ip::{translate_ipv4_to_ipv6, translate_ipv6_to_ipv4};
|
|||||||
mod type_code;
|
mod type_code;
|
||||||
|
|
||||||
/// Translates an ICMP packet to an ICMPv6 packet
|
/// Translates an ICMP packet to an ICMPv6 packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_icmp_to_icmpv6(
|
pub fn translate_icmp_to_icmpv6(
|
||||||
input: IcmpPacket<RawBytes>,
|
input: IcmpPacket<RawBytes>,
|
||||||
new_source: Ipv6Addr,
|
new_source: Ipv6Addr,
|
||||||
@ -68,6 +69,7 @@ pub fn translate_icmp_to_icmpv6(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Translates an ICMPv6 packet to an ICMP packet
|
/// Translates an ICMPv6 packet to an ICMP packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_icmpv6_to_icmp(
|
pub fn translate_icmpv6_to_icmp(
|
||||||
input: Icmpv6Packet<RawBytes>,
|
input: Icmpv6Packet<RawBytes>,
|
||||||
new_source: Ipv4Addr,
|
new_source: Ipv4Addr,
|
||||||
|
@ -11,6 +11,7 @@ use crate::packet::error::PacketError;
|
|||||||
|
|
||||||
/// Best effort translation from an ICMP type and code to an ICMPv6 type and code
|
/// Best effort translation from an ICMP type and code to an ICMPv6 type and code
|
||||||
#[allow(clippy::deprecated_cfg_attr)]
|
#[allow(clippy::deprecated_cfg_attr)]
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_type_and_code_4_to_6(
|
pub fn translate_type_and_code_4_to_6(
|
||||||
icmp_type: IcmpType,
|
icmp_type: IcmpType,
|
||||||
icmp_code: IcmpCode,
|
icmp_code: IcmpCode,
|
||||||
@ -60,6 +61,7 @@ pub fn translate_type_and_code_4_to_6(
|
|||||||
|
|
||||||
/// Best effort translation from an ICMPv6 type and code to an ICMP type and code
|
/// Best effort translation from an ICMPv6 type and code to an ICMP type and code
|
||||||
#[allow(clippy::deprecated_cfg_attr)]
|
#[allow(clippy::deprecated_cfg_attr)]
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_type_and_code_6_to_4(
|
pub fn translate_type_and_code_6_to_4(
|
||||||
icmp_type: Icmpv6Type,
|
icmp_type: Icmpv6Type,
|
||||||
icmp_code: Icmpv6Code,
|
icmp_code: Icmpv6Code,
|
||||||
|
@ -17,6 +17,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Translates an IPv4 packet to an IPv6 packet
|
/// Translates an IPv4 packet to an IPv6 packet
|
||||||
|
#[tracing::instrument(name="xlat_ipv4_ipv6")]
|
||||||
pub fn translate_ipv4_to_ipv6(
|
pub fn translate_ipv4_to_ipv6(
|
||||||
input: Ipv4Packet<Vec<u8>>,
|
input: Ipv4Packet<Vec<u8>>,
|
||||||
new_source: Ipv6Addr,
|
new_source: Ipv6Addr,
|
||||||
@ -69,6 +70,7 @@ pub fn translate_ipv4_to_ipv6(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Translates an IPv6 packet to an IPv4 packet
|
/// Translates an IPv6 packet to an IPv4 packet
|
||||||
|
#[tracing::instrument(name="xlat_ipv6_ipv4")]
|
||||||
pub fn translate_ipv6_to_ipv4(
|
pub fn translate_ipv6_to_ipv4(
|
||||||
input: &Ipv6Packet<Vec<u8>>,
|
input: &Ipv6Packet<Vec<u8>>,
|
||||||
new_source: Ipv4Addr,
|
new_source: Ipv4Addr,
|
||||||
|
@ -6,6 +6,7 @@ use crate::packet::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Translates an IPv4 TCP packet to an IPv6 TCP packet
|
/// Translates an IPv4 TCP packet to an IPv6 TCP packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_tcp4_to_tcp6(
|
pub fn translate_tcp4_to_tcp6(
|
||||||
input: TcpPacket<RawBytes>,
|
input: TcpPacket<RawBytes>,
|
||||||
new_source_addr: Ipv6Addr,
|
new_source_addr: Ipv6Addr,
|
||||||
@ -26,6 +27,7 @@ pub fn translate_tcp4_to_tcp6(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Translates an IPv6 TCP packet to an IPv4 TCP packet
|
/// Translates an IPv6 TCP packet to an IPv4 TCP packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_tcp6_to_tcp4(
|
pub fn translate_tcp6_to_tcp4(
|
||||||
input: TcpPacket<RawBytes>,
|
input: TcpPacket<RawBytes>,
|
||||||
new_source_addr: Ipv4Addr,
|
new_source_addr: Ipv4Addr,
|
||||||
|
@ -6,6 +6,7 @@ use crate::packet::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Translates an IPv4 UDP packet to an IPv6 UDP packet
|
/// Translates an IPv4 UDP packet to an IPv6 UDP packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_udp4_to_udp6(
|
pub fn translate_udp4_to_udp6(
|
||||||
input: UdpPacket<RawBytes>,
|
input: UdpPacket<RawBytes>,
|
||||||
new_source_addr: Ipv6Addr,
|
new_source_addr: Ipv6Addr,
|
||||||
@ -20,6 +21,7 @@ pub fn translate_udp4_to_udp6(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Translates an IPv6 UDP packet to an IPv4 UDP packet
|
/// Translates an IPv6 UDP packet to an IPv4 UDP packet
|
||||||
|
#[profiling::function]
|
||||||
pub fn translate_udp6_to_udp4(
|
pub fn translate_udp6_to_udp4(
|
||||||
input: UdpPacket<RawBytes>,
|
input: UdpPacket<RawBytes>,
|
||||||
new_source_addr: Ipv4Addr,
|
new_source_addr: Ipv4Addr,
|
||||||
|
@ -12,7 +12,7 @@ use tokio::{
|
|||||||
};
|
};
|
||||||
use tun_tap::Mode;
|
use tun_tap::Mode;
|
||||||
|
|
||||||
use crate::Result;
|
use super::TunError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TunDevice {
|
pub struct TunDevice {
|
||||||
@ -29,7 +29,7 @@ impl TunDevice {
|
|||||||
///
|
///
|
||||||
/// The name field can be any string. If `%d` is present in the string,
|
/// The name field can be any string. If `%d` is present in the string,
|
||||||
/// it will be replaced with a unique number.
|
/// it will be replaced with a unique number.
|
||||||
pub async fn new(name: &str) -> Result<Self> {
|
pub async fn new(name: &str) -> Result<Self, TunError> {
|
||||||
// Bring up an rtnetlink connection
|
// Bring up an rtnetlink connection
|
||||||
let (rt_connection, rt_handle, _) = rtnetlink::new_connection().map_err(|err| {
|
let (rt_connection, rt_handle, _) = rtnetlink::new_connection().map_err(|err| {
|
||||||
log::error!("Failed to open rtnetlink connection");
|
log::error!("Failed to open rtnetlink connection");
|
||||||
@ -85,7 +85,11 @@ impl TunDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add an IP address to this device
|
/// Add an IP address to this device
|
||||||
pub async fn add_address(&mut self, ip_address: IpAddr, prefix_len: u8) -> Result<()> {
|
pub async fn add_address(
|
||||||
|
&mut self,
|
||||||
|
ip_address: IpAddr,
|
||||||
|
prefix_len: u8,
|
||||||
|
) -> Result<(), TunError> {
|
||||||
self.rt_handle
|
self.rt_handle
|
||||||
.address()
|
.address()
|
||||||
.add(self.link_index, ip_address, prefix_len)
|
.add(self.link_index, ip_address, prefix_len)
|
||||||
@ -101,7 +105,11 @@ impl TunDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove an IP address from this device
|
/// Remove an IP address from this device
|
||||||
pub async fn remove_address(&mut self, ip_address: IpAddr, prefix_len: u8) -> Result<()> {
|
pub async fn remove_address(
|
||||||
|
&mut self,
|
||||||
|
ip_address: IpAddr,
|
||||||
|
prefix_len: u8,
|
||||||
|
) -> Result<(), TunError> {
|
||||||
// Find the address message that matches the given address
|
// Find the address message that matches the given address
|
||||||
if let Some(address_message) = self
|
if let Some(address_message) = self
|
||||||
.rt_handle
|
.rt_handle
|
||||||
@ -136,7 +144,7 @@ impl TunDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a route to this device
|
/// Add a route to this device
|
||||||
pub async fn add_route(&mut self, destination: IpNet) -> Result<()> {
|
pub async fn add_route(&mut self, destination: IpNet) -> Result<(), TunError> {
|
||||||
match destination {
|
match destination {
|
||||||
IpNet::V4(destination) => {
|
IpNet::V4(destination) => {
|
||||||
self.rt_handle
|
self.rt_handle
|
@ -1,10 +1,8 @@
|
|||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum TunError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
NetlinkError(#[from] rtnetlink::Error),
|
NetlinkError(#[from] rtnetlink::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
5
src/tun/mod.rs
Normal file
5
src/tun/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod device;
|
||||||
|
mod error;
|
||||||
|
|
||||||
|
pub use device::TunDevice;
|
||||||
|
pub use error::TunError;
|
Loading…
x
Reference in New Issue
Block a user