-
Notifications
You must be signed in to change notification settings - Fork 31
Bump: Modernize tun-tap
#18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
c602874
7dcd890
fb7314e
dc72c73
9d1d3a4
b725d51
729dbbd
70d00bd
a8f5af2
44a2aea
1e130ab
7f981a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| name: CI | ||
|
|
||
| on: [push, pull_request] | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| - name: Setup test interface | ||
| run: sudo sh tests/setup.sh | ||
| - name: Build | ||
| run: cargo build --all-targets | ||
| - name: Test | ||
| run: cargo test | ||
| - name: Clippy | ||
| run: cargo clippy --all-targets -- -D warnings | ||
| - name: Doc | ||
| run: cargo doc --no-deps |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,36 @@ | ||
| # 0.2.0 | ||
|
|
||
| ## Breaking Changes | ||
|
|
||
| * Async API completely rewritten: `Stream + Sink` (tokio-core 0.1 / futures 0.1) replaced with | ||
| `AsyncRead + AsyncWrite` (tokio 1.x / `AsyncFd`). The `Async` struct no longer implements | ||
| `Stream` or `Sink`; use `AsyncReadExt` / `AsyncWriteExt` methods instead. | ||
| * Feature renamed: `tokio` → `async`. Enable with `--features async` (on by default). | ||
| * `set_recv_bufsize` removed from `Async`; external buffer sizing is now caller-managed | ||
| via `AsyncRead`. | ||
|
|
||
| ## Dependency Upgrades | ||
|
|
||
| * `tokio-core` 0.1 → `tokio` 1.x (features: net, rt, rt-multi-thread, io-util, macros, time) | ||
| * `futures` 0.1 → removed (tokio provides async traits) | ||
| * `mio` 0.6 → removed (tokio's `AsyncFd` replaces raw mio) | ||
| * `etherparse` 0.9 → 0.17 (dev-dependency) | ||
| * `serial_test` 0.4 → 3.x (dev-dependency) | ||
| * `version-sync` → removed | ||
|
|
||
| ## Code Modernization | ||
|
|
||
| * Edition 2024 compliance: `extern "C"` → `unsafe extern "C"`, removed `extern crate` declarations | ||
| * `build.rs`: removed `extern crate cc;` | ||
| * `[badges]` section removed from `Cargo.toml` (deprecated by crates.io) | ||
| * Travis CI replaced with GitHub Actions (`.github/workflows/ci.yml`) | ||
| * `tests/version.rs` removed (depended on dropped `version-sync`) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are somewhat internal things. I don't think these belong to changelog - that's for consumers of the crate. |
||
|
|
||
| ## Upstream Fixes (since 0.1.4) | ||
|
|
||
| * Fixed `cmd` function in examples to accept arbitrary command instead of hardcoded `"ip"` (#17) | ||
| * Fixed typo in doc comment (#16) | ||
|
|
||
| # 0.1.4 | ||
|
|
||
| * Ability to set nonblocking without tokio (#12). | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| extern crate cc; | ||
|
|
||
| use cc::Build; | ||
|
|
||
| fn main() { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,9 +6,7 @@ | |
| //! The `dump_iface` example is simpler (contains only the reading end), so you want to start with | ||
| //! that. | ||
| //! | ||
| //! You really do want better error handling than all these unwraps. | ||
|
|
||
| extern crate tun_tap; | ||
| //! that. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicated. |
||
|
|
||
| use std::process::Command; | ||
| use std::sync::Arc; | ||
|
|
@@ -19,10 +17,12 @@ use tun_tap::{Iface, Mode}; | |
|
|
||
| /// The packet data. Note that it is prefixed by 4 bytes ‒ two bytes are flags, another two are | ||
| /// protocol. 8, 0 is IPv4, 134, 221 is IPv6. <https://en.wikipedia.org/wiki/EtherType#Examples>. | ||
| const PING: &[u8] = &[0, 0, 8, 0, 69, 0, 0, 84, 44, 166, 64, 0, 64, 1, 247, 40, 10, 107, 1, 2, 10, | ||
| 107, 1, 3, 8, 0, 62, 248, 19, 160, 0, 2, 232, 228, 34, 90, 0, 0, 0, 0, 216, 83, 3, 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]; | ||
| const PING: &[u8] = &[ | ||
| 0, 0, 8, 0, 69, 0, 0, 84, 44, 166, 64, 0, 64, 1, 247, 40, 10, 107, 1, 2, 10, 107, 1, 3, 8, 0, | ||
| 62, 248, 19, 160, 0, 2, 232, 228, 34, 90, 0, 0, 0, 0, 216, 83, 3, 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, | ||
| ]; | ||
|
|
||
| /// Run a shell command. Panic if it fails in any way. | ||
| fn cmd(cmd: &str, args: &[&str]) { | ||
|
|
@@ -55,7 +55,7 @@ fn main() { | |
| assert!(amount == PING.len()); | ||
| } | ||
| }); | ||
| let reader = thread::spawn(move || { | ||
| thread::spawn(move || { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason you're no longer waiting for the reader - and more importantly, dropping any panics it might have produced. |
||
| // MTU + TUN header | ||
| let mut buffer = vec![0; 1504]; | ||
| loop { | ||
|
|
@@ -65,8 +65,5 @@ fn main() { | |
| println!("Packet: {:?}", &buffer[4..size]); | ||
| } | ||
| }); | ||
| writer.join() | ||
| .unwrap(); | ||
| reader.join() | ||
| .unwrap(); | ||
| writer.join().unwrap(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,29 +3,27 @@ | |
| //! This creates an interface, configures the kernel endpoint and sends pings to that endpoint. It | ||
| //! prints whatever packets come back (which should include the pong responses). | ||
| //! | ||
| //! This does essentialy the same as the `pingpoing` example. However, instead of threads, this | ||
| //! This does essentially the same as the `pingpong` example. However, instead of threads, this | ||
| //! uses tokio asynchronous event loop to multiplex between the two directions. | ||
| //! | ||
| //! You really do want better error handling than all these unwraps. | ||
|
|
||
| extern crate futures; | ||
| extern crate tokio_core; | ||
| extern crate tun_tap; | ||
|
|
||
| use std::process::Command; | ||
| use std::time::Duration; | ||
|
|
||
| use futures::{Future, Stream}; | ||
| use tokio_core::reactor::{Core, Interval}; | ||
| use tokio::io::{AsyncReadExt, AsyncWriteExt}; | ||
| use tokio::time; | ||
| use tun_tap::r#async::Async; | ||
| use tun_tap::{Iface, Mode}; | ||
| use tun_tap::async::Async; | ||
|
|
||
| /// The packet data. Note that it is prefixed by 4 bytes ‒ two bytes are flags, another two are | ||
| /// The packet data. Note that it is prefixed by 4 bytes — two bytes are flags, another two are | ||
| /// protocol. 8, 0 is IPv4, 134, 221 is IPv6. <https://en.wikipedia.org/wiki/EtherType#Examples>. | ||
| const PING: &[u8] = &[0, 0, 8, 0, 69, 0, 0, 84, 44, 166, 64, 0, 64, 1, 247, 40, 10, 107, 1, 2, 10, | ||
| 107, 1, 3, 8, 0, 62, 248, 19, 160, 0, 2, 232, 228, 34, 90, 0, 0, 0, 0, 216, 83, 3, 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]; | ||
| const PING: &[u8] = &[ | ||
| 0, 0, 8, 0, 69, 0, 0, 84, 44, 166, 64, 0, 64, 1, 247, 40, 10, 107, 1, 2, 10, 107, 1, 3, 8, 0, | ||
| 62, 248, 19, 160, 0, 2, 232, 228, 34, 90, 0, 0, 0, 0, 216, 83, 3, 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, | ||
| ]; | ||
|
|
||
| /// Run a shell command. Panic if it fails in any way. | ||
| fn cmd(cmd: &str, args: &[&str]) { | ||
|
|
@@ -38,26 +36,29 @@ fn cmd(cmd: &str, args: &[&str]) { | |
| assert!(ecode.success(), "Failed to execte {}", cmd); | ||
| } | ||
|
|
||
| fn main() { | ||
| #[tokio::main] | ||
| async fn main() { | ||
| let iface = Iface::new("testtun%d", Mode::Tun).unwrap(); | ||
| eprintln!("Iface: {:?}", iface); | ||
| // Configure the „local“ (kernel) endpoint. Kernel is (the host) 10.107.1.3, we (the app) | ||
| // Configure the "local" (kernel) endpoint. Kernel is (the host) 10.107.1.3, we (the app) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On one hand, you're replacing dashes with the more correct long ones, on the other, you're removing the typographically correct quotes? |
||
| // pretend to be 10.107.1.2. | ||
| cmd("ip", &["addr", "add", "dev", iface.name(), "10.107.1.3/24"]); | ||
| cmd("ip", &["link", "set", "up", "dev", iface.name()]); | ||
| let mut core = Core::new().unwrap(); | ||
| let iface = Async::new(iface, &core.handle()).unwrap(); | ||
| let (sink, stream) = iface.split(); | ||
| let writer = Interval::new(Duration::from_secs(1), &core.handle()) | ||
| .unwrap() | ||
| .map(|_| { | ||
| let (mut reader, mut writer) = tokio::io::split(Async::new(iface).unwrap()); | ||
| let write_task = tokio::spawn(async move { | ||
| let mut interval = time::interval(Duration::from_secs(1)); | ||
| loop { | ||
| interval.tick().await; | ||
| println!("Sending ping"); | ||
| PING.to_owned() | ||
| }) | ||
| .forward(sink); | ||
| let reader = stream.for_each(|packet| { | ||
| println!("Received: {:?}", packet); | ||
| Ok(()) | ||
| writer.write_all(PING).await.unwrap(); | ||
| } | ||
| }); | ||
| let read_task = tokio::spawn(async move { | ||
| let mut buf = vec![0u8; 1504]; | ||
| loop { | ||
| let n = reader.read(&mut buf).await.unwrap(); | ||
| println!("Received: {:?}", &buf[..n]); | ||
| } | ||
| }); | ||
| core.run(reader.join(writer)).unwrap(); | ||
| tokio::try_join!(write_task, read_task).unwrap(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the motivation behind making it run forever instead of just once? The PR seems to be about modernizing things, but you seem to be doing a lot more for unexplained reasons. |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think renaming to
asyncis entirely correct - this does depend on a specific async runtime, tokio.Also, I don't think it makes sense to list documentation to Rust, namely how to enable features - and besides, nobody really does it by that flag, they do so through their Cargo.toml.