Giter Site home page Giter Site logo

tokio-tun's People

Contributors

beepbop0 avatar dndx avatar ftsell avatar oll3 avatar paolobarbolini avatar rgafiyatullin avatar rtzoeller avatar yaa110 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

tokio-tun's Issues

Send + Sync bounds on the Error type seem to be unnecessary

I started building a small project using this crate and quickly found that the bounds on the return type from TunBuilder::try_build were slowly spreading throughout my project so I dove in to see why it was necessary.

I took Send + Sync from Error here: https://github.com/yaa110/tokio-tun/blob/master/src/result.rs#L2 and the crate builds fine. Is there a particular reason to require these traits?

My main issue is that it cannot be trivially converted to and from std::result::Result<T, Box<dyn std::error::Error>> so it ends up spreading throughout.

If I try to return it in a function that returns Result<(), Box<dyn std::error::Error>>, I get this error:

error[E0277]: the size for values of type `dyn std::error::Error + Sync + std::marker::Send` cannot be known at compilation time
  --> src/bin/main.rs:11:45
   |
11 |     let mut netty = NettyStack::new(if_name)?;
   |                                             ^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn std::error::Error + Sync + std::marker::Send`
   = note: required because of the requirements on the impl of `std::error::Error` for `Box<dyn std::error::Error + Sync + std::marker::Send>`
   = note: required because of the requirements on the impl of `From<Box<dyn std::error::Error + Sync + std::marker::Send>>` for `Box<dyn std::error::Error>`
   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, Box<dyn std::error::Error + Sync + std::marker::Send>>>` for `Result<(), Box<dyn std::error::Error>>`

If I try to return Result<T, Box<dyn std::error::Error>> in a function that returns Result<T, Box<dyn std::error::Error + Send + Sync>>:

error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
  --> src/bin/main.rs:15:74
   |
15 |     add_address(if_name, Ipv4Addr::new(10, 0, 0, 1).into(), handle).await?;
   |                                                                          ^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn std::error::Error`
   = note: required because of the requirements on the impl of `std::error::Error` for `Box<dyn std::error::Error>`
   = note: required because of the requirements on the impl of `From<Box<dyn std::error::Error>>` for `Box<dyn std::error::Error + Sync + std::marker::Send>`
   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, Box<dyn std::error::Error>>>` for `Result<(), Box<dyn std::error::Error + Sync + std::marker::Send>>`

Concurrent writing and reading hangs event loop

It seems that tokio-tun hangs when trying to write and read concurrently. Is this expected? Is there some pattern that allows concurrent reading and writing?

Here is a minimal example. After 5 seconds reader stops working and packet is actually never sent. Running this example with just reader or just writer (replacing reader loop with sleep) works as expected.

Tokio 1.0.1, Tokio-tun 0.3.1, Rust 1.49 stable.

use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio_tun::result::Result;
use tokio_tun::TunBuilder;
use tokio::time::{sleep, Duration};


#[tokio::main]
async fn main() -> Result<()> {
    let tun = TunBuilder::new()
        .name("")
        .tap(false)
        .packet_info(false)
        .mtu(1350)
        .up()
        .address(Ipv4Addr::new(10, 0, 0, 1))
        .destination(Ipv4Addr::new(10, 0, 0, 1))
        .broadcast(Ipv4Addr::BROADCAST)
        .netmask(Ipv4Addr::new(255, 0, 0, 0))
        .try_build()?;

    println!("-----------");
    println!("tun created");
    println!("-----------");

    println!(
        "┌ name: {}\n├ fd: {}\n├ mtu: {}\n├ flags: {}\n├ address: {}\n├ destination: {}\n├ broadcast: {}\n└ netmask: {}",
        tun.name(),
        tun.as_raw_fd(),
        tun.mtu().unwrap(),
        tun.flags().unwrap(),
        tun.address().unwrap(),
        tun.destination().unwrap(),
        tun.broadcast().unwrap(),
        tun.netmask().unwrap(),
    );

    println!("---------------------");
    println!("ping 10.1.0.2 to test");
    println!("---------------------");

    let (mut reader, mut writer) = tokio::io::split(tun);

    tokio::spawn( async move {
        sleep(Duration::from_secs(5)).await;
        let packet = [69, 0, 0, 64, 0, 0, 64, 0, 64, 6, 112, 21, 10, 0, 0, 2, 3, 209, 188, 208, 114, 4, 1, 187, 232, 33, 115, 193, 0, 0, 0, 0, 176, 2, 255, 255, 15, 234, 0, 0, 2, 4, 5, 180, 1, 3, 3, 6, 1, 1, 8, 10, 62, 53, 78, 151, 0, 0, 0, 0, 4, 2, 0, 0];
        println!("Sending packet!");
        writer.write(&packet).await.expect("Error!");
        println!("Packet sent");
    });

    let mut buf = [0u8; 1024];
    loop {
        let n = reader.read(&mut buf).await?;
        println!("reading {} bytes: {:?}", n, &buf[..n]);
    }
}

Panic when calling flush on the WriteHalf returned from tokio-tun builder

I've a very simple program that creates a tun device, splits it, and writes to the write half. The write succeeds, but when I attempt to call flush it panics. Here's my sample:

#![deny(clippy::all)]
#![warn(clippy::pedantic)]

use tokio::io::AsyncWriteExt;
use std::os::fd::AsRawFd;
use tokio_tun::Tun;
use std::net::Ipv4Addr;

#[tokio::main]
async fn main() -> () {
    let tun = Tun::builder()
        .name("foo")
        .tap(false)
        .packet_info(false)
        .up()
        .address(Ipv4Addr::new(10, 0, 0, 1))
        .destination(Ipv4Addr::new(10, 1, 0, 1))
        .broadcast(Ipv4Addr::BROADCAST)
        .netmask(Ipv4Addr::new(255, 255, 255, 0))
        .try_build()
        .unwrap();

    println!("tun created, name: {}, fd: {}", tun.name(), tun.as_raw_fd());

    let (_reader, mut writer) = tokio::io::split(tun);

    // Just a basic ICMP request packet
    let packet = [
        69, 0, 0, 84, 0, 0, 64, 0, 64, 1, 38, 166, 10, 1, 0, 2, 10, 0, 0, 1,
        0, 0, 102, 216, 0, 7, 5, 26, 197, 176, 29, 101, 0, 0, 0, 0, 238, 29, 4,
        0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
        50, 51, 52, 53, 54, 55];

    writer.write_all(&packet).await.unwrap();
    writer.flush().await.unwrap();
}

When I invoke this small program with root privs via the following command, I generate a stack trace:

$ cargo b && sudo RUST_BACKTRACE=full ./target/debug/pinger-tokio

$ cargo b && sudo RUST_BACKTRACE=full ./target/debug/pinger-tokio
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
tun created, name: foo, fd: 9
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', src/main.rs:36:26
stack backtrace:
   0:     0x559179961511 - std::backtrace_rs::backtrace::libunwind::trace::h66dc1c6acf794faa
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x559179961511 - std::backtrace_rs::backtrace::trace_unsynchronized::ha80d20099a67f790
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x559179961511 - std::sys_common::backtrace::_print_fmt::h7b959d43f35f16d4
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:65:5
   3:     0x559179961511 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hdaa196410d9ee0b9
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:44:22
   4:     0x559179982cef - core::fmt::rt::Argument::fmt::h0ddfbbe8be3f80d0
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/fmt/rt.rs:138:9
   5:     0x559179982cef - core::fmt::write::h66b3c629f3d623e4
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/fmt/mod.rs:1094:21
   6:     0x55917995e927 - std::io::Write::write_fmt::hb6d80fba4115e0c2
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/io/mod.rs:1714:15
   7:     0x559179961325 - std::sys_common::backtrace::_print::h1a49cfb0cf3cce17
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:47:5
   8:     0x559179961325 - std::sys_common::backtrace::print::hca95c2d0055e42a2
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:34:9
   9:     0x559179962853 - std::panicking::default_hook::{{closure}}::hc03c01c56bca600c
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:269:22
  10:     0x5591799625e4 - std::panicking::default_hook::hb2cb5315b6634f1c
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:288:9
  11:     0x559179962dd9 - std::panicking::rust_panic_with_hook::h75cd912a39a34e8a
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:705:13
  12:     0x559179962cd7 - std::panicking::begin_panic_handler::{{closure}}::h1498b46f7849e167
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:597:13
  13:     0x559179961976 - std::sys_common::backtrace::__rust_end_short_backtrace::hd36a39b27b98086b
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:151:18
  14:     0x559179962a22 - rust_begin_unwind
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:593:5
  15:     0x559179875273 - core::panicking::panic_fmt::h98ef273141454c23
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/panicking.rs:67:14
  16:     0x559179875743 - core::result::unwrap_failed::h26e7d1a596cddd61
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/result.rs:1651:5
  17:     0x55917987a2cd - core::result::Result<T,E>::unwrap::hfba736a1f516fc32
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/result.rs:1076:23
  18:     0x55917987d0b2 - pinger_tokio::main::{{closure}}::hb4c29fabc0e0a84c
                               at /home/rjw/pinger-tokio/src/main.rs:36:5
  19:     0x559179876674 - tokio::runtime::park::CachedParkThread::block_on::{{closure}}::hc2102838ad1ff373
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/park.rs:282:63
  20:     0x5591798764a5 - tokio::runtime::coop::with_budget::h7bd2944232a4b354
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/coop.rs:107:5
  21:     0x5591798764a5 - tokio::runtime::coop::budget::h35f9a719fa4c7073
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/coop.rs:73:5
  22:     0x5591798764a5 - tokio::runtime::park::CachedParkThread::block_on::hdd97a7aecde53be4
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/park.rs:282:31
  23:     0x55917987c2e5 - tokio::runtime::context::blocking::BlockingRegionGuard::block_on::h8bcad03ed3746a7a
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/context/blocking.rs:66:9
  24:     0x55917987c056 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}::hdc0db8febb28906c
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/scheduler/multi_thread/mod.rs:87:13
  25:     0x55917987b8fc - tokio::runtime::context::runtime::enter_runtime::h83da395e19220ae7
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/context/runtime.rs:65:16
  26:     0x55917987c011 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on::h0b01f4b37ea5a961
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/scheduler/multi_thread/mod.rs:86:9
  27:     0x5591798767cb - tokio::runtime::runtime::Runtime::block_on::hc28efc14991c6fd4
                               at /home/rjw/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.32.0/src/runtime/runtime.rs:349:45
  28:     0x55917987a9fd - pinger_tokio::main::h5657d9d59fbfb77f
                               at /home/rjw/pinger-tokio/src/main.rs:36:5
  29:     0x55917987719b - core::ops::function::FnOnce::call_once::h9646c2d630b860c2
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/ops/function.rs:250:5
  30:     0x55917987c5de - std::sys_common::backtrace::__rust_begin_short_backtrace::h574604846fa0a270
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/sys_common/backtrace.rs:135:18
  31:     0x559179877a11 - std::rt::lang_start::{{closure}}::he00ac19dd4a14f13
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/rt.rs:166:18
  32:     0x55917995b3eb - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h87e9a912d8a0de33
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/core/src/ops/function.rs:284:13
  33:     0x55917995b3eb - std::panicking::try::do_call::ha8d57d42181c12cf
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:500:40
  34:     0x55917995b3eb - std::panicking::try::h2fdb2d19c253437c
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:464:19
  35:     0x55917995b3eb - std::panic::catch_unwind::h9fe5959d2e133449
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panic.rs:142:14
  36:     0x55917995b3eb - std::rt::lang_start_internal::{{closure}}::ha072eb7bbeaa0b6a
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/rt.rs:148:48
  37:     0x55917995b3eb - std::panicking::try::do_call::h983dae29f79ed5db
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:500:40
  38:     0x55917995b3eb - std::panicking::try::h15014751f4b412ba
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panicking.rs:464:19
  39:     0x55917995b3eb - std::panic::catch_unwind::hf837426183b1055f
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/panic.rs:142:14
  40:     0x55917995b3eb - std::rt::lang_start_internal::h2bbe0b58b2b89a9f
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/rt.rs:148:20
  41:     0x5591798779ea - std::rt::lang_start::hf6639bc367ab8881
                               at /rustc/d5c2e9c342b358556da91d61ed4133f6f50fc0c3/library/std/src/rt.rs:165:17
  42:     0x55917987aaae - main
  43:     0x7f4c90c900d0 - <unknown>
  44:     0x7f4c90c90189 - __libc_start_main
  45:     0x559179875a45 - _start
  46:                0x0 - <unknown>

I'd like to note that if I use async-tun, I can write to the Tun device fine. The difference may be in the tokio::split vs. Tun.writer() calls, I'm not sure. Thought, it appears this is not the case, as changing the sample program above to forego calling tokio::io::split and instead just writing and flushing the Tun device directly produces the same result. e.g.,

    // Just a basic ICMP request packet
    let packet = [
        69, 0, 0, 84, 0, 0, 64, 0, 64, 1, 38, 166, 10, 1, 0, 2, 10, 0, 0, 1,
        0, 0, 102, 216, 0, 7, 5, 26, 197, 176, 29, 101, 0, 0, 0, 0, 238, 29, 4,
        0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
        50, 51, 52, 53, 54, 55];

    tun.write_all(&packet).await.unwrap();
    tun.flush().await.unwrap();

I should also note my platform info:

$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/rjw/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.72.1 (d5c2e9c34 2023-09-13)

$ uname -a Linux angband 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

As you can see, I am running on Ubuntu under WSL. I'm not sure this is relevant but, one never knows.

Create a device from a `RawFd`

Tun implements AsRawFd but it would be useful to support FromRawFd or moral equivalent.
The use case is if you inherit a fd for a tun device or receive it from another process, but want to use it in an async context with tokio-tun instead of treating it as a standard file.

Obviously in this case you do not have a handle to the tun interface description and can't get MTU/address etc. which prevents a trivial implementation of FromRawFd.

Add IPv6 support

It would be nice if a user could choose whether they want to use IPv4 or IPv6 on their TUN device.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.