Switch logging to use tracing instead of log

Tracing has support for intervals and a great os_log integration.
This commit is contained in:
Jett Chen 2023-08-27 11:43:17 +08:00
parent 60cfd95789
commit e643d9dd41
14 changed files with 297 additions and 8 deletions

181
Cargo.lock generated
View file

@ -125,6 +125,28 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bindgen"
version = "0.64.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4"
dependencies = [
"bitflags 1.3.2",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 1.0.109",
"which",
]
[[package]] [[package]]
name = "bindgen" name = "bindgen"
version = "0.65.1" version = "0.65.1"
@ -179,6 +201,7 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
name = "burrow" name = "burrow"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"caps", "caps",
"clap", "clap",
"env_logger", "env_logger",
@ -188,6 +211,11 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
"tracing",
"tracing-journald",
"tracing-log",
"tracing-oslog",
"tracing-subscriber",
"tun", "tun",
] ]
@ -902,6 +930,16 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]]
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.19" version = "0.4.19"
@ -1020,6 +1058,16 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.31.1" version = "0.31.1"
@ -1079,6 +1127,35 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]] [[package]]
name = "password-hash" name = "password-hash"
version = "0.4.2" version = "0.4.2"
@ -1283,6 +1360,12 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.9.1" version = "2.9.1"
@ -1382,6 +1465,15 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.1.0" version = "1.1.0"
@ -1397,6 +1489,12 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.9" version = "0.4.9"
@ -1506,6 +1604,16 @@ dependencies = [
"syn 2.0.22", "syn 2.0.22",
] ]
[[package]]
name = "thread_local"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.22" version = "0.3.22"
@ -1603,9 +1711,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"pin-project-lite", "pin-project-lite",
"tracing-attributes",
"tracing-core", "tracing-core",
] ]
[[package]]
name = "tracing-attributes"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.22",
]
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.31" version = "0.1.31"
@ -1613,6 +1733,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-journald"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd"
dependencies = [
"libc",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-oslog"
version = "0.1.2"
source = "git+https://github.com/Stormshield-robinc/tracing-oslog#c4d21a95e70cdd62b1cea04fc4f8be1c547cad6c"
dependencies = [
"bindgen 0.64.0",
"cc",
"cfg-if",
"fnv",
"once_cell",
"parking_lot",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -1626,7 +1798,7 @@ name = "tun"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bindgen", "bindgen 0.65.1",
"byteorder", "byteorder",
"fehler", "fehler",
"futures", "futures",
@ -1641,6 +1813,7 @@ dependencies = [
"ssri", "ssri",
"tempfile", "tempfile",
"tokio", "tokio",
"tracing",
"widestring", "widestring",
"windows", "windows",
"zip", "zip",
@ -1705,6 +1878,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View file

@ -7,9 +7,15 @@ edition = "2021"
crate-type = ["lib", "staticlib"] crate-type = ["lib", "staticlib"]
[dependencies] [dependencies]
tokio = { version = "1.21", features = ["rt", "sync", "io-util", "macros"] } anyhow = "1.0"
tokio = { version = "1.21", features = ["rt", "macros", "sync", "io-util"] }
tun = { version = "0.1", path = "../tun", features = ["serde"] } tun = { version = "0.1", path = "../tun", features = ["serde"] }
clap = { version = "4.3.2", features = ["derive"] } clap = { version = "4.3.2", features = ["derive"] }
tracing = "0.1"
tracing-log = "0.1"
tracing-journald = "0.3"
tracing-oslog = {git = "https://github.com/Stormshield-robinc/tracing-oslog"}
tracing-subscriber = "0.3"
env_logger = "0.10" env_logger = "0.10"
log = "0.4" log = "0.4"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View file

@ -1,5 +1,8 @@
use tracing::instrument;
// Check capabilities on Linux // Check capabilities on Linux
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[instrument]
pub fn ensure_root() { pub fn ensure_root() {
use caps::{has_cap, CapSet, Capability}; use caps::{has_cap, CapSet, Capability};
@ -19,6 +22,7 @@ pub fn ensure_root() {
// Check for root user on macOS // Check for root user on macOS
#[cfg(target_vendor = "apple")] #[cfg(target_vendor = "apple")]
#[instrument]
pub fn ensure_root() { pub fn ensure_root() {
use nix::unistd::Uid; use nix::unistd::Uid;
@ -30,6 +34,7 @@ pub fn ensure_root() {
} }
#[cfg(target_family = "windows")] #[cfg(target_family = "windows")]
#[instrument]
pub fn ensure_root() { pub fn ensure_root() {
todo!() todo!()
} }

View file

@ -1,3 +1,4 @@
#![deny(missing_debug_implementations)]
pub mod ensureroot; pub mod ensureroot;
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]

View file

@ -1,8 +1,14 @@
use anyhow::Context;
use std::mem; use std::mem;
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
use std::os::fd::FromRawFd; use std::os::fd::FromRawFd;
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use tracing::instrument;
use tracing_log::LogTracer;
use tracing_oslog::OsLogger;
use tracing_subscriber::{prelude::*, FmtSubscriber};
use tokio::io::Result; use tokio::io::Result;
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
use burrow::retrieve; use burrow::retrieve;
@ -58,10 +64,21 @@ async fn try_start() -> Result<()> {
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[instrument]
async fn try_retrieve() -> Result<()> { async fn try_retrieve() -> Result<()> {
LogTracer::init().context("Failed to initialize LogTracer").unwrap();
if cfg!(target_os = "linux") || cfg!(target_vendor = "apple") {
let maybe_layer = system_log().unwrap();
if let Some(layer) = maybe_layer {
let logger = layer.with_subscriber(FmtSubscriber::new());
tracing::subscriber::set_global_default(logger).context("Failed to set the global tracing subscriber").unwrap();
}
}
burrow::ensureroot::ensure_root(); burrow::ensureroot::ensure_root();
let iface2 = retrieve(); let iface2 = retrieve();
println!("{}", iface2); tracing::info!("{}", iface2);
Ok(()) Ok(())
} }
@ -89,17 +106,17 @@ async fn try_stop() -> Result<()> {
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> { async fn main() -> Result<()> {
println!("Platform: {}", std::env::consts::OS); tracing::info!("Platform: {}", std::env::consts::OS);
let cli = Cli::parse(); let cli = Cli::parse();
match &cli.command { match &cli.command {
Commands::Start(..) => { Commands::Start(..) => {
try_start().await.unwrap(); try_start().await.unwrap();
println!("FINISHED"); tracing::info!("FINISHED");
} }
Commands::Retrieve(..) => { Commands::Retrieve(..) => {
try_retrieve().await.unwrap(); try_retrieve().await.unwrap();
println!("FINISHED"); tracing::info!("FINISHED");
} }
Commands::Stop => { Commands::Stop => {
try_stop().await.unwrap(); try_stop().await.unwrap();
@ -109,3 +126,20 @@ async fn main() -> Result<()> {
Ok(()) Ok(())
} }
#[cfg(target_os = "linux")]
fn system_log() -> anyhow::Result<Option<tracing_journald::Layer>> {
let maybe_journald = tracing_journald::layer();
match maybe_journald {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
tracing::trace!("journald not found");
Ok(None)
},
_ => Ok(Some(maybe_journald?))
}
}
#[cfg(target_vendor = "apple")]
fn system_log() -> anyhow::Result<Option<OsLogger>> {
Ok(Some(OsLogger::new("com.hackclub.burrow", "default")))
}

View file

@ -10,6 +10,7 @@ nix = { version = "0.26", features = ["ioctl"] }
socket2 = "0.4" socket2 = "0.4"
tokio = { version = "1.28", features = [] } tokio = { version = "1.28", features = [] }
byteorder = "1.4" byteorder = "1.4"
tracing = "0.1"
log = "0.4" log = "0.4"
serde = { version = "1", features = ["derive"], optional = true } serde = { version = "1", features = ["derive"], optional = true }

View file

@ -1,3 +1,5 @@
#![deny(missing_debug_implementations)]
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
#[path = "windows/mod.rs"] #[path = "windows/mod.rs"]
mod imp; mod imp;

View file

@ -1,17 +1,21 @@
use std::io; use std::io;
use tokio::io::unix::AsyncFd; use tokio::io::unix::AsyncFd;
use tracing::instrument;
#[derive(Debug)]
pub struct TunInterface { pub struct TunInterface {
inner: AsyncFd<crate::TunInterface>, inner: AsyncFd<crate::TunInterface>,
} }
impl TunInterface { impl TunInterface {
#[instrument]
pub fn new(tun: crate::TunInterface) -> io::Result<Self> { pub fn new(tun: crate::TunInterface) -> io::Result<Self> {
Ok(Self { Ok(Self {
inner: AsyncFd::new(tun)?, inner: AsyncFd::new(tun)?,
}) })
} }
#[instrument]
pub async fn write(&self, buf: &[u8]) -> io::Result<usize> { pub async fn write(&self, buf: &[u8]) -> io::Result<usize> {
loop { loop {
let mut guard = self.inner.writable().await?; let mut guard = self.inner.writable().await?;
@ -22,6 +26,7 @@ impl TunInterface {
} }
} }
#[instrument]
pub async fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { pub async fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
loop { loop {
let mut guard = self.inner.readable_mut().await?; let mut guard = self.inner.readable_mut().await?;

View file

@ -1,12 +1,13 @@
use byteorder::{ByteOrder, NetworkEndian}; use byteorder::{ByteOrder, NetworkEndian};
use fehler::throws; use fehler::throws;
use libc::{c_char, iovec, writev, AF_INET, AF_INET6}; use libc::{c_char, iovec, writev, AF_INET, AF_INET6};
use log::info; use tracing::info;
use socket2::{Domain, SockAddr, Socket, Type}; use socket2::{Domain, SockAddr, Socket, Type};
use std::io::IoSlice; use std::io::IoSlice;
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsRawFd, RawFd};
use std::{io::Error, mem}; use std::{io::Error, mem};
use tracing::instrument;
mod kern_control; mod kern_control;
mod sys; mod sys;
@ -23,16 +24,19 @@ pub struct TunInterface {
impl TunInterface { impl TunInterface {
#[throws] #[throws]
#[instrument]
pub fn new() -> TunInterface { pub fn new() -> TunInterface {
Self::new_with_options(TunOptions::new())? Self::new_with_options(TunOptions::new())?
} }
#[throws] #[throws]
#[instrument]
pub fn new_with_options(_: TunOptions) -> TunInterface { pub fn new_with_options(_: TunOptions) -> TunInterface {
TunInterface::connect(0)? TunInterface::connect(0)?
} }
#[throws] #[throws]
#[instrument]
fn connect(index: u32) -> TunInterface { fn connect(index: u32) -> TunInterface {
use socket2::{Domain, Protocol, Socket, Type}; use socket2::{Domain, Protocol, Socket, Type};
@ -48,6 +52,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn name(&self) -> String { pub fn name(&self) -> String {
let mut buf = [0 as c_char; sys::IFNAMSIZ]; let mut buf = [0 as c_char; sys::IFNAMSIZ];
let mut len = buf.len() as sys::socklen_t; let mut len = buf.len() as sys::socklen_t;
@ -62,6 +67,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
fn ifreq(&self) -> sys::ifreq { fn ifreq(&self) -> sys::ifreq {
let mut iff: sys::ifreq = unsafe { mem::zeroed() }; let mut iff: sys::ifreq = unsafe { mem::zeroed() };
iff.ifr_name = string_to_ifname(&self.name()?); iff.ifr_name = string_to_ifname(&self.name()?);
@ -69,6 +75,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_ipv4_addr(&self, addr: Ipv4Addr) { pub fn set_ipv4_addr(&self, addr: Ipv4Addr) {
let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); let addr = SockAddr::from(SocketAddrV4::new(addr, 0));
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
@ -78,6 +85,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn ipv4_addr(&self) -> Ipv4Addr { pub fn ipv4_addr(&self) -> Ipv4Addr {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_addr(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_addr(fd, &mut iff) })?;
@ -87,11 +95,15 @@ impl TunInterface {
#[throws] #[throws]
fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R { fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
let span = tracing::info_span!("perform", fd = self.as_raw_fd());
let _enter = span.enter();
let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?; let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?;
perform(socket.as_raw_fd())? perform(socket.as_raw_fd())?
} }
#[throws] #[throws]
#[instrument]
pub fn mtu(&self) -> i32 { pub fn mtu(&self) -> i32 {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_mtu(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_mtu(fd, &mut iff) })?;
@ -101,6 +113,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_mtu(&self, mtu: i32) { pub fn set_mtu(&self, mtu: i32) {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
iff.ifr_ifru.ifru_mtu = mtu; iff.ifr_ifru.ifru_mtu = mtu;
@ -109,6 +122,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn netmask(&self) -> Ipv4Addr { pub fn netmask(&self) -> Ipv4Addr {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_netmask(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_netmask(fd, &mut iff) })?;
@ -120,6 +134,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_netmask(&self, addr: Ipv4Addr) { pub fn set_netmask(&self, addr: Ipv4Addr) {
let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); let addr = SockAddr::from(SocketAddrV4::new(addr, 0));
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
@ -133,6 +148,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn send(&self, buf: &[u8]) -> usize { pub fn send(&self, buf: &[u8]) -> usize {
use std::io::ErrorKind; use std::io::ErrorKind;
let proto = match buf[0] >> 4 { let proto = match buf[0] >> 4 {

View file

@ -8,7 +8,7 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4};
use std::os::fd::RawFd; use std::os::fd::RawFd;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use log::info; use tracing::{info, instrument};
use libc::in6_ifreq; use libc::in6_ifreq;
@ -23,11 +23,13 @@ pub struct TunInterface {
impl TunInterface { impl TunInterface {
#[throws] #[throws]
#[instrument]
pub fn new() -> TunInterface { pub fn new() -> TunInterface {
Self::new_with_options(TunOptions::new())? Self::new_with_options(TunOptions::new())?
} }
#[throws] #[throws]
#[instrument]
pub(crate) fn new_with_options(options: TunOptions) -> TunInterface { pub(crate) fn new_with_options(options: TunOptions) -> TunInterface {
let file = OpenOptions::new() let file = OpenOptions::new()
.read(true) .read(true)
@ -59,6 +61,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn name(&self) -> String { pub fn name(&self) -> String {
let mut iff = unsafe { mem::zeroed() }; let mut iff = unsafe { mem::zeroed() };
unsafe { sys::tun_get_iff(self.socket.as_raw_fd(), &mut iff)? }; unsafe { sys::tun_get_iff(self.socket.as_raw_fd(), &mut iff)? };
@ -66,6 +69,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
fn ifreq(&self) -> sys::ifreq { fn ifreq(&self) -> sys::ifreq {
let mut iff: sys::ifreq = unsafe { mem::zeroed() }; let mut iff: sys::ifreq = unsafe { mem::zeroed() };
iff.ifr_name = string_to_ifname(&self.name()?); iff.ifr_name = string_to_ifname(&self.name()?);
@ -73,6 +77,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
fn in6_ifreq(&self) -> in6_ifreq { fn in6_ifreq(&self) -> in6_ifreq {
let mut iff: in6_ifreq = unsafe { mem::zeroed() }; let mut iff: in6_ifreq = unsafe { mem::zeroed() };
iff.ifr6_ifindex = self.index()?; iff.ifr6_ifindex = self.index()?;
@ -80,6 +85,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn index(&self) -> i32 { pub fn index(&self) -> i32 {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_index(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_index(fd, &mut iff) })?;
@ -87,6 +93,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_ipv4_addr(&self, addr: Ipv4Addr) { pub fn set_ipv4_addr(&self, addr: Ipv4Addr) {
let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); let addr = SockAddr::from(SocketAddrV4::new(addr, 0));
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
@ -96,6 +103,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn ipv4_addr(&self) -> Ipv4Addr { pub fn ipv4_addr(&self) -> Ipv4Addr {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_addr(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_addr(fd, &mut iff) })?;
@ -104,6 +112,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_broadcast_addr(&self, addr: Ipv4Addr) { pub fn set_broadcast_addr(&self, addr: Ipv4Addr) {
let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); let addr = SockAddr::from(SocketAddrV4::new(addr, 0));
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
@ -117,6 +126,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn broadcast_addr(&self) -> Ipv4Addr { pub fn broadcast_addr(&self) -> Ipv4Addr {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_brdaddr(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_brdaddr(fd, &mut iff) })?;
@ -126,6 +136,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_ipv6_addr(&self, addr: Ipv6Addr) { pub fn set_ipv6_addr(&self, addr: Ipv6Addr) {
let mut iff = self.in6_ifreq()?; let mut iff = self.in6_ifreq()?;
iff.ifr6_addr.s6_addr = addr.octets(); iff.ifr6_addr.s6_addr = addr.octets();
@ -134,6 +145,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_mtu(&self, mtu: i32) { pub fn set_mtu(&self, mtu: i32) {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
iff.ifr_ifru.ifru_mtu = mtu; iff.ifr_ifru.ifru_mtu = mtu;
@ -142,6 +154,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn mtu(&self) -> i32 { pub fn mtu(&self) -> i32 {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_mtu(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_mtu(fd, &mut iff) })?;
@ -151,6 +164,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn set_netmask(&self, addr: Ipv4Addr) { pub fn set_netmask(&self, addr: Ipv4Addr) {
let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); let addr = SockAddr::from(SocketAddrV4::new(addr, 0));
@ -167,6 +181,7 @@ impl TunInterface {
} }
#[throws] #[throws]
#[instrument]
pub fn netmask(&self) -> Ipv4Addr { pub fn netmask(&self) -> Ipv4Addr {
let mut iff = self.ifreq()?; let mut iff = self.ifreq()?;
self.perform(|fd| unsafe { sys::if_get_netmask(fd, &mut iff) })?; self.perform(|fd| unsafe { sys::if_get_netmask(fd, &mut iff) })?;
@ -179,17 +194,24 @@ impl TunInterface {
#[throws] #[throws]
fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R { fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
let span = tracing::info_span!("perform");
let _enter = span.enter();
let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?; let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?;
perform(socket.as_raw_fd())? perform(socket.as_raw_fd())?
} }
#[throws] #[throws]
fn perform6<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R { fn perform6<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
let span = tracing::info_span!("perform");
let _enter = span.enter();
let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?; let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?;
perform(socket.as_raw_fd())? perform(socket.as_raw_fd())?
} }
#[throws] #[throws]
#[instrument]
pub fn send(&self, buf: &[u8]) -> usize { pub fn send(&self, buf: &[u8]) -> usize {
self.socket.send(buf)? self.socket.send(buf)?
} }

View file

@ -2,6 +2,7 @@ use std::{
io::{Error, Read}, io::{Error, Read},
os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
}; };
use tracing::instrument;
use super::TunOptions; use super::TunOptions;
@ -41,11 +42,13 @@ impl IntoRawFd for TunInterface {
impl TunInterface { impl TunInterface {
#[throws] #[throws]
#[instrument]
pub fn recv(&mut self, buf: &mut [u8]) -> usize { pub fn recv(&mut self, buf: &mut [u8]) -> usize {
self.socket.read(buf)? self.socket.read(buf)?
} }
} }
#[instrument]
pub fn ifname_to_string(buf: [libc::c_char; libc::IFNAMSIZ]) -> String { pub fn ifname_to_string(buf: [libc::c_char; libc::IFNAMSIZ]) -> String {
// TODO: Switch to `CStr::from_bytes_until_nul` when stabilized // TODO: Switch to `CStr::from_bytes_until_nul` when stabilized
unsafe { unsafe {
@ -56,6 +59,7 @@ pub fn ifname_to_string(buf: [libc::c_char; libc::IFNAMSIZ]) -> String {
} }
} }
#[instrument]
pub fn string_to_ifname(name: &str) -> [libc::c_char; libc::IFNAMSIZ] { pub fn string_to_ifname(name: &str) -> [libc::c_char; libc::IFNAMSIZ] {
let mut buf = [0 as libc::c_char; libc::IFNAMSIZ]; let mut buf = [0 as libc::c_char; libc::IFNAMSIZ];
let len = name.len().min(buf.len()); let len = name.len().min(buf.len());

View file

@ -5,15 +5,18 @@ use std::{
mem::MaybeUninit, mem::MaybeUninit,
os::unix::io::{AsRawFd, IntoRawFd, RawFd}, os::unix::io::{AsRawFd, IntoRawFd, RawFd},
}; };
use tracing::instrument;
use crate::TunInterface; use crate::TunInterface;
#[derive(Debug)]
pub struct TunQueue { pub struct TunQueue {
socket: socket2::Socket, socket: socket2::Socket,
} }
impl TunQueue { impl TunQueue {
#[throws] #[throws]
#[instrument]
pub fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> usize { pub fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> usize {
self.socket.recv(buf)? self.socket.recv(buf)?
} }

View file

@ -1,3 +1,4 @@
use std::fmt::Debug;
use fehler::throws; use fehler::throws;
use std::io::Error; use std::io::Error;
use std::ptr; use std::ptr;
@ -14,6 +15,15 @@ pub struct TunInterface {
name: String, name: String,
} }
impl Debug for TunInterface {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TunInterface")
.field("handle", &"SYS_WINTUN_ADAPTER_HANDLE".to_string())
.field("name", &self.name)
.finish()
}
}
impl TunInterface { impl TunInterface {
#[throws] #[throws]
pub fn new() -> TunInterface { pub fn new() -> TunInterface {

View file

@ -1 +1,2 @@
#[derive(Debug)]
pub struct TunQueue; pub struct TunQueue;