TAPD interfaces
==============
Usage
-----
First, add the following to your `Cargo.toml`:
```toml
[dependencies]
tapd = "0.1"
```
Example
-------
The following example creates and configures a TAP interface and starts reading
packets from it.
```rust
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.