tapd

Crates.iotapd
lib.rstapd
version0.1.32
created_at2025-10-31 06:53:09.373533+00
updated_at2025-12-03 01:26:40.555941+00
descriptionwrap tun/tap device to tapd app/lib
homepage
repository
max_upload_size
id1909551
size113,563
Jacky WU (wuhongzhi)

documentation

README

TAPD interfaces

Usage

First, add the following to your Cargo.toml:

[dependencies]
tapd = "0.1"

Example

The following example creates and configures a TAP interface and starts reading packets from it.

use anyhow::{Result, bail};
use nix::{
    fcntl::{self, FcntlArg},
    sys::stat::{self, SFlag},
};
use std::{
    env::{self, args},
    io::{IsTerminal, stdin, stdout},
    os::fd::AsFd,
};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
    let mut argv = args();
    let app = argv.next().unwrap();

    let blocking = env::var_os("TAPD_ASYNC").is_none();
    match argv.len() {
        2 => {
            let tap1 = &argv.next().unwrap();
            let tap2 = &argv.next().unwrap();
            tapd::new(blocking).pipe_tun(tap1, tap2)?.join_all().await[0]
        }
        1 => {
            let tap1 = &argv.next().unwrap();
            if setup_stdio(stdin()) && setup_stdio(stdout()) {
                tapd::new(blocking).pipe_std(tap1)?.join_all().await[0]
            }
        }
        _ => {}
    }
    bail!("Usage: {app:?} [dev1 dev2 | dev]");
}

fn setup_stdio<T: AsFd + IsTerminal>(fd: T) -> bool {
    if fd.is_terminal() {
        return false;
    }
    match stat::fstat(fd.as_fd()) {
        Ok(stat) => {
            if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFIFO) {
                let _ = fcntl::fcntl(fd.as_fd(), FcntlArg::F_SETPIPE_SZ(1 << 20));
            }
            true
        }
        Err(_) => false,
    }
}

Linux

You will need the tun module to be loaded and root is required to create interfaces.

Commit count: 0

cargo fmt