Setting up buildsystem to allow for BPF builds
This commit is contained in:
parent
e35fa043b3
commit
c26c06d62c
1
.cargo/cross-images/.gitignore
vendored
Normal file
1
.cargo/cross-images/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/*.dockerfile.timestamp
|
11
.cargo/cross-images/bpfex-unknown-none.dockerfile
Normal file
11
.cargo/cross-images/bpfex-unknown-none.dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Cross image for building bpfel and bpfeb targets
|
||||||
|
|
||||||
|
FROM rust:latest
|
||||||
|
ARG TOOLCHAIN_CHANNEL
|
||||||
|
|
||||||
|
# Install the needed toolcahin components
|
||||||
|
RUN rustup install ${TOOLCHAIN_CHANNEL}
|
||||||
|
RUN rustup component add rust-src --toolchain ${TOOLCHAIN_CHANNEL}
|
||||||
|
|
||||||
|
# Install the BFP linker
|
||||||
|
RUN cargo install bpf-linker
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -5,5 +5,5 @@
|
|||||||
"pnet",
|
"pnet",
|
||||||
"Protomask",
|
"Protomask",
|
||||||
"rtnetlink"
|
"rtnetlink"
|
||||||
]
|
],
|
||||||
}
|
}
|
32
.vscode/tasks.json
vendored
32
.vscode/tasks.json
vendored
@ -2,24 +2,40 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "cargo",
|
"type": "shell",
|
||||||
"command": "build",
|
"command": "make",
|
||||||
|
"args": [
|
||||||
|
"target/x86_64-unknown-linux-musl/debug/protomask"
|
||||||
|
],
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$rustc",
|
"$rustc",
|
||||||
"$rust-panic"
|
"$rust-panic"
|
||||||
],
|
],
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"label": "rust: cargo build"
|
"label": "rust: build [target: x86_64-unknown-linux-musl]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "cargo",
|
"type": "shell",
|
||||||
"command": "test",
|
"command": "make",
|
||||||
|
"args": [
|
||||||
|
"target/x86_64-unknown-linux-musl/release/protomask"
|
||||||
|
],
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$rustc",
|
"$rustc",
|
||||||
"$rust-panic"
|
"$rust-panic"
|
||||||
],
|
],
|
||||||
"group": "test",
|
"group": "build",
|
||||||
"label": "rust: cargo test"
|
"label": "rust: build [target: x86_64-unknown-linux-musl] [profile: release]"
|
||||||
}
|
},
|
||||||
|
// {
|
||||||
|
// "type": "cargo",
|
||||||
|
// "command": "test",
|
||||||
|
// "problemMatcher": [
|
||||||
|
// "$rustc",
|
||||||
|
// "$rust-panic"
|
||||||
|
// ],
|
||||||
|
// "group": "test",
|
||||||
|
// "label": "rust: cargo test"
|
||||||
|
// }
|
||||||
]
|
]
|
||||||
}
|
}
|
111
Cargo.toml
111
Cargo.toml
@ -1,56 +1,57 @@
|
|||||||
[package]
|
# [package]
|
||||||
name = "protomask"
|
# name = "protomask"
|
||||||
version = "0.2.0"
|
# version = "0.2.0"
|
||||||
authors = ["Evan Pratten <ewpratten@gmail.com>"]
|
# authors = ["Evan Pratten <ewpratten@gmail.com>"]
|
||||||
edition = "2021"
|
# edition = "2021"
|
||||||
description = "A user space NAT64 implementation"
|
# description = "A user space NAT64 implementation"
|
||||||
readme = "README.md"
|
# readme = "README.md"
|
||||||
homepage = "https://github.com/ewpratten/protomask"
|
# homepage = "https://github.com/ewpratten/protomask"
|
||||||
documentation = "https://docs.rs/protomask"
|
# documentation = "https://docs.rs/protomask"
|
||||||
repository = "https://github.com/ewpratten/protomask"
|
# repository = "https://github.com/ewpratten/protomask"
|
||||||
license = "GPL-3.0"
|
# license = "GPL-3.0"
|
||||||
keywords = []
|
# keywords = []
|
||||||
categories = []
|
# categories = []
|
||||||
|
# # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
# [dependencies]
|
||||||
|
# protomask-tun = { path = "protomask-tun", version = "0.1.0" }
|
||||||
|
# tokio = { version = "1.29.1", features = [
|
||||||
|
# "macros",
|
||||||
|
# "rt-multi-thread",
|
||||||
|
# # "process",
|
||||||
|
# "sync"
|
||||||
|
# ] }
|
||||||
|
# clap = { version = "4.3.11", features = ["derive"] }
|
||||||
|
# serde = { version = "1.0.171", features = ["derive"] }
|
||||||
|
# ipnet = { version = "2.8.0", features = ["serde"] }
|
||||||
|
# hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
|
||||||
|
# owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||||
|
# toml = "0.7.6"
|
||||||
|
# log = "0.4.19"
|
||||||
|
# fern = "0.6.2"
|
||||||
|
# serde_path_to_error = "0.1.13"
|
||||||
|
# thiserror = "1.0.43"
|
||||||
|
# tun-tap = "0.1.3"
|
||||||
|
# bimap = "0.6.3"
|
||||||
|
# pnet_packet = "0.34.0"
|
||||||
|
# rtnetlink = "0.13.0"
|
||||||
|
# futures = "0.3.28"
|
||||||
|
# prometheus = "0.13.3"
|
||||||
|
# lazy_static = "1.4.0"
|
||||||
|
# [[bin]]
|
||||||
|
# name = "protomask"
|
||||||
|
# path = "src/cli/main.rs"
|
||||||
|
# [package.metadata.deb]
|
||||||
|
# section = "network"
|
||||||
|
# assets = [
|
||||||
|
# ["target/release/protomask", "/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"]
|
||||||
|
# depends = []
|
||||||
|
# maintainer-scripts = "./debian/"
|
||||||
|
# systemd-units = { enable = false }
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[workspace]
|
||||||
[dependencies]
|
resolver = "2"
|
||||||
protomask-tun = { path = "protomask-tun", version = "0.1.0" }
|
members = ["protomask", "protomask-ebpf"]
|
||||||
tokio = { version = "1.29.1", features = [
|
|
||||||
"macros",
|
|
||||||
"rt-multi-thread",
|
|
||||||
# "process",
|
|
||||||
"sync"
|
|
||||||
] }
|
|
||||||
clap = { version = "4.3.11", features = ["derive"] }
|
|
||||||
serde = { version = "1.0.171", features = ["derive"] }
|
|
||||||
ipnet = { version = "2.8.0", features = ["serde"] }
|
|
||||||
hyper = { version = "0.14.27", features = ["server", "http1", "tcp"] }
|
|
||||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
|
||||||
toml = "0.7.6"
|
|
||||||
log = "0.4.19"
|
|
||||||
fern = "0.6.2"
|
|
||||||
serde_path_to_error = "0.1.13"
|
|
||||||
thiserror = "1.0.43"
|
|
||||||
tun-tap = "0.1.3"
|
|
||||||
bimap = "0.6.3"
|
|
||||||
pnet_packet = "0.34.0"
|
|
||||||
rtnetlink = "0.13.0"
|
|
||||||
futures = "0.3.28"
|
|
||||||
prometheus = "0.13.3"
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "protomask"
|
|
||||||
path = "src/cli/main.rs"
|
|
||||||
|
|
||||||
[package.metadata.deb]
|
|
||||||
section = "network"
|
|
||||||
assets = [
|
|
||||||
["target/release/protomask", "/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"]
|
|
||||||
depends = []
|
|
||||||
maintainer-scripts = "./debian/"
|
|
||||||
systemd-units = { enable = false }
|
|
||||||
|
5
Cross.toml
Normal file
5
Cross.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[target.bpfel-unknown-none]
|
||||||
|
image = "protomask/bpfex-unknown-none"
|
||||||
|
|
||||||
|
[target.bpfeb-unknown-none]
|
||||||
|
image = "protomask/bpfex-unknown-none"
|
51
Makefile
51
Makefile
@ -1,17 +1,48 @@
|
|||||||
# 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')
|
PROTOMASK_SRC = protomask/Cargo.toml $(shell find protomask/src/ -type f -name '*.rs')
|
||||||
|
PROTOMASK_EBPF_SRC = protomask-ebpf/Cargo.toml $(shell find protomask-ebpf/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" protomask/Cargo.toml)
|
||||||
|
TOOLCHAIN_CHANNEL = $(shell sed -n -r "s/^channel = \"(.+)\"/\1/p" rust-toolchain.toml)
|
||||||
|
|
||||||
target/x86_64-unknown-linux-musl/release/protomask: $(SRC)
|
.PHONY: clean
|
||||||
cross build --target x86_64-unknown-linux-musl --release
|
|
||||||
|
|
||||||
target/aarch64-unknown-linux-musl/release/protomask: $(SRC)
|
# x64 Protomask binary (Debug)
|
||||||
cross build --target aarch64-unknown-linux-musl --release
|
target/x86_64-unknown-linux-musl/debug/protomask: $(PROTOMASK_SRC) target/bpfel-unknown-none/debug/protomask-ebpf
|
||||||
|
cross build --target x86_64-unknown-linux-musl --bin protomask
|
||||||
|
|
||||||
target/x86_64-unknown-linux-musl/debian/protomask_${CRATE_VERSION}_amd64.deb: target/x86_64-unknown-linux-musl/release/protomask
|
# x64 Protomask binary (Release)
|
||||||
cargo deb --target x86_64-unknown-linux-musl --no-build
|
target/x86_64-unknown-linux-musl/release/protomask: $(PROTOMASK_SRC) target/bpfel-unknown-none/release/protomask-ebpf
|
||||||
|
cross build --target x86_64-unknown-linux-musl --bin protomask --release
|
||||||
|
|
||||||
target/aarch64-unknown-linux-musl/debian/protomask_${CRATE_VERSION}_arm64.deb: target/aarch64-unknown-linux-musl/release/protomask
|
# Docker image used for building bpfel and bpfeb images
|
||||||
cargo deb --target aarch64-unknown-linux-musl --no-build
|
.cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp: .cargo/cross-images/bpfex-unknown-none.dockerfile
|
||||||
|
docker build -t protomask/bpfex-unknown-none -f $< --build-arg TOOLCHAIN_CHANNEL=$(TOOLCHAIN_CHANNEL) .cargo/cross-images
|
||||||
|
touch .cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp
|
||||||
|
|
||||||
|
# Little-Endian BPF (Debug)
|
||||||
|
target/bpfel-unknown-none/debug/protomask-ebpf: $(PROTOMASK_EBPF_SRC) .cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp
|
||||||
|
cross build -Z build-std=core --target bpfel-unknown-none --bin protomask-ebpf
|
||||||
|
|
||||||
|
# Little-Endian BPF (Release)
|
||||||
|
target/bpfel-unknown-none/release/protomask-ebpf: $(PROTOMASK_EBPF_SRC) .cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp
|
||||||
|
cargo build -Z build-std=core --target bpfel-unknown-none --bin protomask-ebpf --release
|
||||||
|
|
||||||
|
# Big-Endian BPF (Debug)
|
||||||
|
target/bpfeb-unknown-none/debug/protomask-ebpf: $(PROTOMASK_EBPF_SRC) .cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp
|
||||||
|
cross build -Z build-std=core --target bpfeb-unknown-none --bin protomask-ebpf
|
||||||
|
|
||||||
|
# Big-Endian BPF (Release)
|
||||||
|
target/bpfeb-unknown-none/release/protomask-ebpf: $(PROTOMASK_EBPF_SRC) .cargo/cross-images/bpfex-unknown-none.dockerfile.timestamp
|
||||||
|
cargo build -Z build-std=core --target bpfeb-unknown-none --bin protomask-ebpf --release
|
||||||
|
|
||||||
|
# Cleanup task
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
# target/x86_64-unknown-linux-musl/debian/protomask_${CRATE_VERSION}_amd64.deb: target/x86_64-unknown-linux-musl/release/protomask
|
||||||
|
# cargo deb --target x86_64-unknown-linux-musl --no-build
|
||||||
|
|
||||||
|
# target/aarch64-unknown-linux-musl/debian/protomask_${CRATE_VERSION}_arm64.deb: target/aarch64-unknown-linux-musl/release/protomask
|
||||||
|
# cargo deb --target aarch64-unknown-linux-musl --no-build
|
||||||
|
5
protomask-ebpf/Cargo.toml
Normal file
5
protomask-ebpf/Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[package]
|
||||||
|
name = "protomask-ebpf"
|
||||||
|
publish = false
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
5
protomask-ebpf/src/main.rs
Normal file
5
protomask-ebpf/src/main.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
mod panic;
|
||||||
|
|
6
protomask-ebpf/src/panic.rs
Normal file
6
protomask-ebpf/src/panic.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
unsafe { core::hint::unreachable_unchecked() }
|
||||||
|
}
|
@ -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,10 +0,0 @@
|
|||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error(transparent)]
|
|
||||||
IoError(#[from] std::io::Error),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
NetlinkError(#[from] rtnetlink::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
@ -1,5 +0,0 @@
|
|||||||
mod error;
|
|
||||||
mod tun;
|
|
||||||
|
|
||||||
pub use error::{Error, Result};
|
|
||||||
pub use tun::TunDevice;
|
|
@ -1,226 +0,0 @@
|
|||||||
use std::{
|
|
||||||
io::{Read, Write},
|
|
||||||
net::IpAddr,
|
|
||||||
os::fd::{AsRawFd, FromRawFd},
|
|
||||||
};
|
|
||||||
|
|
||||||
use futures::TryStreamExt;
|
|
||||||
use ipnet::IpNet;
|
|
||||||
use tokio::{
|
|
||||||
sync::{broadcast, mpsc},
|
|
||||||
task,
|
|
||||||
};
|
|
||||||
use tun_tap::Mode;
|
|
||||||
|
|
||||||
use crate::Result;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TunDevice {
|
|
||||||
device: tun_tap::Iface,
|
|
||||||
rt_handle: rtnetlink::Handle,
|
|
||||||
link_index: u32,
|
|
||||||
mtu: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TunDevice {
|
|
||||||
/// Create and bring up a new TUN device
|
|
||||||
///
|
|
||||||
/// ## Name format
|
|
||||||
///
|
|
||||||
/// The name field can be any string. If `%d` is present in the string,
|
|
||||||
/// it will be replaced with a unique number.
|
|
||||||
pub async fn new(name: &str) -> Result<Self> {
|
|
||||||
// Bring up an rtnetlink connection
|
|
||||||
let (rt_connection, rt_handle, _) = rtnetlink::new_connection().map_err(|err| {
|
|
||||||
log::error!("Failed to open rtnetlink connection");
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
tokio::spawn(rt_connection);
|
|
||||||
|
|
||||||
// Create the TUN device
|
|
||||||
let tun_device = tun_tap::Iface::without_packet_info(name, Mode::Tun)?;
|
|
||||||
log::debug!("Created new TUN device: {}", tun_device.name());
|
|
||||||
|
|
||||||
// Get access to the link through rtnetlink
|
|
||||||
// NOTE: I don't think there is any way this can fail, so `except` is probably OK
|
|
||||||
let tun_link = rt_handle
|
|
||||||
.link()
|
|
||||||
.get()
|
|
||||||
.match_name(tun_device.name().to_owned())
|
|
||||||
.execute()
|
|
||||||
.try_next()
|
|
||||||
.await?
|
|
||||||
.expect("Failed to access newly created TUN device");
|
|
||||||
|
|
||||||
// Bring the link up
|
|
||||||
rt_handle
|
|
||||||
.link()
|
|
||||||
.set(tun_link.header.index)
|
|
||||||
.up()
|
|
||||||
.execute()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to bring up link");
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
log::debug!("Brought {} up", tun_device.name());
|
|
||||||
|
|
||||||
// Read the link MTU
|
|
||||||
let mtu: usize =
|
|
||||||
std::fs::read_to_string(format!("/sys/class/net/{}/mtu", tun_device.name()))
|
|
||||||
.expect("Failed to read link MTU")
|
|
||||||
.strip_suffix("\n")
|
|
||||||
.unwrap()
|
|
||||||
.parse()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
device: tun_device,
|
|
||||||
rt_handle,
|
|
||||||
link_index: tun_link.header.index,
|
|
||||||
mtu,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an IP address to this device
|
|
||||||
pub async fn add_address(&mut self, ip_address: IpAddr, prefix_len: u8) -> Result<()> {
|
|
||||||
self.rt_handle
|
|
||||||
.address()
|
|
||||||
.add(self.link_index, ip_address, prefix_len)
|
|
||||||
.execute()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to add address {} to link", ip_address);
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove an IP address from this device
|
|
||||||
pub async fn remove_address(&mut self, ip_address: IpAddr, prefix_len: u8) -> Result<()> {
|
|
||||||
// Find the address message that matches the given address
|
|
||||||
if let Some(address_message) = self
|
|
||||||
.rt_handle
|
|
||||||
.address()
|
|
||||||
.get()
|
|
||||||
.set_link_index_filter(self.link_index)
|
|
||||||
.set_address_filter(ip_address)
|
|
||||||
.set_prefix_length_filter(prefix_len)
|
|
||||||
.execute()
|
|
||||||
.try_next()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to find address {} on link", ip_address);
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?
|
|
||||||
{
|
|
||||||
// Delete the address
|
|
||||||
self.rt_handle
|
|
||||||
.address()
|
|
||||||
.del(address_message)
|
|
||||||
.execute()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to remove address {} from link", ip_address);
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a route to this device
|
|
||||||
pub async fn add_route(&mut self, destination: IpNet) -> Result<()> {
|
|
||||||
match destination {
|
|
||||||
IpNet::V4(destination) => {
|
|
||||||
self.rt_handle
|
|
||||||
.route()
|
|
||||||
.add()
|
|
||||||
.v4()
|
|
||||||
.output_interface(self.link_index)
|
|
||||||
.destination_prefix(destination.addr(), destination.prefix_len())
|
|
||||||
.execute()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to add route {} to link", destination);
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
IpNet::V6(destination) => {
|
|
||||||
self.rt_handle
|
|
||||||
.route()
|
|
||||||
.add()
|
|
||||||
.v6()
|
|
||||||
.output_interface(self.link_index)
|
|
||||||
.destination_prefix(destination.addr(), destination.prefix_len())
|
|
||||||
.execute()
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
log::error!("Failed to add route {} to link", destination);
|
|
||||||
log::error!("{}", err);
|
|
||||||
err
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Spawns worker threads, and returns a tx/rx pair for the caller to interact with them
|
|
||||||
pub async fn spawn_worker(&self) -> (mpsc::Sender<Vec<u8>>, broadcast::Receiver<Vec<u8>>) {
|
|
||||||
// Create a channel for packets to be sent to the caller
|
|
||||||
let (tx_to_caller, rx_from_worker) = broadcast::channel(65535);
|
|
||||||
|
|
||||||
// Create a channel for packets being received from the caller
|
|
||||||
let (tx_to_worker, mut rx_from_caller) = mpsc::channel(65535);
|
|
||||||
|
|
||||||
// Clone some values for use in worker threads
|
|
||||||
let mtu = self.mtu;
|
|
||||||
let device_fd = self.device.as_raw_fd();
|
|
||||||
|
|
||||||
// Create a task that broadcasts all incoming packets
|
|
||||||
let _rx_task = task::spawn_blocking(move || {
|
|
||||||
// Build a buffer to read packets into
|
|
||||||
let mut buffer = vec![0u8; mtu];
|
|
||||||
|
|
||||||
// Create a file to access the TUN device
|
|
||||||
let mut device = unsafe { std::fs::File::from_raw_fd(device_fd) };
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Read a packet from the TUN device
|
|
||||||
let packet_len = device.read(&mut buffer[..]).unwrap();
|
|
||||||
let packet = buffer[..packet_len].to_vec();
|
|
||||||
|
|
||||||
// Broadcast the packet to all listeners
|
|
||||||
tx_to_caller.send(packet).unwrap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a task that sends all outgoing packets
|
|
||||||
let _tx_task = task::spawn(async move {
|
|
||||||
// Create a file to access the TUN device
|
|
||||||
let mut device = unsafe { std::fs::File::from_raw_fd(device_fd) };
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Wait for a packet to be sent
|
|
||||||
let packet: Vec<u8> = rx_from_caller.recv().await.unwrap();
|
|
||||||
|
|
||||||
// Write the packet to the TUN device
|
|
||||||
device.write_all(&packet[..]).unwrap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a task that sends all outgoing packets
|
|
||||||
let _tx_task = task::spawn_blocking(|| {});
|
|
||||||
|
|
||||||
// Return an rx/tx pair for the caller to interact with the workers
|
|
||||||
(tx_to_worker, rx_from_worker)
|
|
||||||
}
|
|
||||||
}
|
|
18
protomask/Cargo.toml
Normal file
18
protomask/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "protomask"
|
||||||
|
version = "0.2.0"
|
||||||
|
authors = ["Evan Pratten <ewpratten@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
description = "A user space NAT64 implementation"
|
||||||
|
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]
|
||||||
|
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "sync"] }
|
||||||
|
clap = { version = "4.3.11", features = ["derive"] }
|
||||||
|
|
5
protomask/src/main.rs
Normal file
5
protomask/src/main.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
pub async fn main(){
|
||||||
|
|
||||||
|
}
|
15
rust-toolchain.toml
Normal file
15
rust-toolchain.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly-2023-07-26"
|
||||||
|
# components = [
|
||||||
|
# "cargo",
|
||||||
|
# "clippy",
|
||||||
|
# "rust-docs",
|
||||||
|
# "rust-src",
|
||||||
|
# "rust-std",
|
||||||
|
# "rustc",
|
||||||
|
# "rustfmt",
|
||||||
|
# ]
|
||||||
|
# targets = [
|
||||||
|
# "bpfel-unknown-none",
|
||||||
|
# "bpfeb-unknown-none",
|
||||||
|
# ]
|
Loading…
x
Reference in New Issue
Block a user