From c0d86458338c4a14c92f54ea4bd555a71684ee6b Mon Sep 17 00:00:00 2001 From: lbl <1791778603@qq.com> Date: Tue, 31 Dec 2024 11:26:59 +0800 Subject: [PATCH] replace tun --- Cargo.lock | 231 ++++++-- vnt/Cargo.toml | 4 +- vnt/src/core/mod.rs | 9 - vnt/src/handle/recv_data/server.rs | 11 +- vnt/src/handle/tun_tap/mod.rs | 12 +- .../tun_tap/{windows.rs => platform.rs} | 6 +- vnt/src/handle/tun_tap/tun_handler.rs | 14 +- vnt/src/handle/tun_tap/unix.rs | 154 ------ vnt/src/tun_tap_device/create_device.rs | 148 ++++-- vnt/src/tun_tap_device/tun_create_helper.rs | 11 +- vnt/tun/Cargo.toml | 34 -- vnt/tun/src/android/mod.rs | 61 --- vnt/tun/src/device.rs | 24 - vnt/tun/src/lib.rs | 33 -- vnt/tun/src/linux/device.rs | 281 ---------- vnt/tun/src/linux/mod.rs | 4 - vnt/tun/src/linux/route.rs | 25 - vnt/tun/src/linux/sys.rs | 21 - vnt/tun/src/macos/device.rs | 297 ----------- vnt/tun/src/macos/mod.rs | 5 - vnt/tun/src/macos/route.rs | 20 - vnt/tun/src/macos/sys.rs | 119 ----- vnt/tun/src/packet/arp/mod.rs | 1 - vnt/tun/src/packet/arp/packet.rs | 123 ----- vnt/tun/src/packet/ethernet/mod.rs | 2 - vnt/tun/src/packet/ethernet/packet.rs | 80 --- vnt/tun/src/packet/ethernet/protocol.rs | 141 ----- vnt/tun/src/packet/mod.rs | 67 --- vnt/tun/src/unix/fd.rs | 68 --- vnt/tun/src/unix/mod.rs | 28 - vnt/tun/src/unix/sockaddr.rs | 67 --- vnt/tun/src/windows/check.rs | 167 ------ vnt/tun/src/windows/device.rs | 94 ---- vnt/tun/src/windows/ffi.rs | 502 ------------------ vnt/tun/src/windows/mod.rs | 44 -- vnt/tun/src/windows/netsh.rs | 48 -- vnt/tun/src/windows/route.rs | 33 -- vnt/tun/src/windows/tap/mod.rs | 185 ------- vnt/tun/src/windows/tun/mod.rs | 363 ------------- vnt/tun/src/windows/tun/packet.rs | 64 --- vnt/tun/src/windows/tun/wintun_log.rs | 48 -- vnt/tun/src/windows/tun/wintun_raw.rs | 449 ---------------- 42 files changed, 317 insertions(+), 3781 deletions(-) rename vnt/src/handle/tun_tap/{windows.rs => platform.rs} (96%) delete mode 100644 vnt/src/handle/tun_tap/unix.rs delete mode 100644 vnt/tun/Cargo.toml delete mode 100644 vnt/tun/src/android/mod.rs delete mode 100644 vnt/tun/src/device.rs delete mode 100644 vnt/tun/src/lib.rs delete mode 100644 vnt/tun/src/linux/device.rs delete mode 100644 vnt/tun/src/linux/mod.rs delete mode 100644 vnt/tun/src/linux/route.rs delete mode 100644 vnt/tun/src/linux/sys.rs delete mode 100644 vnt/tun/src/macos/device.rs delete mode 100644 vnt/tun/src/macos/mod.rs delete mode 100644 vnt/tun/src/macos/route.rs delete mode 100644 vnt/tun/src/macos/sys.rs delete mode 100644 vnt/tun/src/packet/arp/mod.rs delete mode 100644 vnt/tun/src/packet/arp/packet.rs delete mode 100644 vnt/tun/src/packet/ethernet/mod.rs delete mode 100644 vnt/tun/src/packet/ethernet/packet.rs delete mode 100644 vnt/tun/src/packet/ethernet/protocol.rs delete mode 100644 vnt/tun/src/packet/mod.rs delete mode 100644 vnt/tun/src/unix/fd.rs delete mode 100644 vnt/tun/src/unix/mod.rs delete mode 100644 vnt/tun/src/unix/sockaddr.rs delete mode 100644 vnt/tun/src/windows/check.rs delete mode 100644 vnt/tun/src/windows/device.rs delete mode 100644 vnt/tun/src/windows/ffi.rs delete mode 100644 vnt/tun/src/windows/mod.rs delete mode 100644 vnt/tun/src/windows/netsh.rs delete mode 100644 vnt/tun/src/windows/route.rs delete mode 100644 vnt/tun/src/windows/tap/mod.rs delete mode 100644 vnt/tun/src/windows/tun/mod.rs delete mode 100644 vnt/tun/src/windows/tun/packet.rs delete mode 100644 vnt/tun/src/windows/tun/wintun_log.rs delete mode 100644 vnt/tun/src/windows/tun/wintun_raw.rs diff --git a/Cargo.lock b/Cargo.lock index 056d3d9..d06df61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,7 +139,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools", @@ -152,7 +152,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.60", + "syn 2.0.93", "which", ] @@ -164,9 +164,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -204,6 +204,26 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "c2rust-bitfields" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367e5d1b30f28be590b6b3868da1578361d29d9bfac516d22f497d28ed7c9055" +dependencies = [ + "c2rust-bitfields-derive", +] + +[[package]] +name = "c2rust-bitfields-derive" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a279db9c50c4024eeca1a763b6e0f033848ce74e83e47454bcf8a8a98f7b0b56" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cbc" version = "0.1.2" @@ -239,6 +259,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "cfg_aliases" version = "0.2.1" @@ -520,6 +546,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -571,7 +606,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", ] [[package]] @@ -621,6 +656,17 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "getifaddrs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba121d81ab5ea05b0cd5858516266800bf965531a794f7ac58e3eeb804f364f" +dependencies = [ + "bitflags 2.6.0", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "getopts" version = "0.2.21" @@ -803,10 +849,10 @@ dependencies = [ ] [[package]] -name = "ioctl-sys" -version = "0.8.0" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "itertools" @@ -858,9 +904,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -946,7 +992,7 @@ dependencies = [ "serde-value", "serde_json", "serde_yaml", - "thiserror", + "thiserror 1.0.58", "thread-id", "typemap-ors", "winapi", @@ -972,12 +1018,31 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" +[[package]] +name = "mac_address" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8836fae9d0d4be2c8b4efcdd79e828a2faa058a90d005abf42f91cac5493a08e" +dependencies = [ + "nix 0.28.0", + "winapi", +] + [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1013,10 +1078,35 @@ checksum = "433419f898328beca4f2c6c73a1b52540658d92b0a99f0269330457e0fd998d5" dependencies = [ "cc", "libc", - "thiserror", + "thiserror 1.0.58", "winapi", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -1271,14 +1361,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.93", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1291,7 +1381,7 @@ checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" dependencies = [ "once_cell", "protobuf-support", - "thiserror", + "thiserror 1.0.58", ] [[package]] @@ -1306,7 +1396,7 @@ dependencies = [ "protobuf-parse", "regex", "tempfile", - "thiserror", + "thiserror 1.0.58", ] [[package]] @@ -1321,7 +1411,7 @@ dependencies = [ "protobuf", "protobuf-support", "tempfile", - "thiserror", + "thiserror 1.0.58", "which", ] @@ -1331,7 +1421,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" dependencies = [ - "thiserror", + "thiserror 1.0.58", ] [[package]] @@ -1526,7 +1616,7 @@ version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1614,7 +1704,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -1658,7 +1748,7 @@ checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", ] [[package]] @@ -1838,9 +1928,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", @@ -1874,7 +1964,16 @@ version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.58", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", ] [[package]] @@ -1885,7 +1984,18 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.93", ] [[package]] @@ -1940,7 +2050,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", ] [[package]] @@ -1972,17 +2082,29 @@ dependencies = [ ] [[package]] -name = "tun" -version = "0.1.0" +name = "tun-rs" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53141e64197ff7e758b8152615e50bb4a3b18c970738876e7906d31f242c7d6e" dependencies = [ - "ioctl-sys", + "bitflags 2.6.0", + "byteorder", + "bytes", + "c2rust-bitfields", + "cfg-if", + "encoding_rs", + "getifaddrs", + "ipnet", "libc", "libloading", "log", - "rand", - "sha2", - "widestring", - "winapi", + "mac_address", + "nix 0.29.0", + "scopeguard", + "thiserror 2.0.9", + "windows-sys 0.59.0", + "winreg", + "wintun-bindings", ] [[package]] @@ -2001,7 +2123,7 @@ dependencies = [ "rustls", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.58", "utf-8", ] @@ -2148,7 +2270,7 @@ dependencies = [ "anyhow", "bytes", "cbc", - "cfg_aliases", + "cfg_aliases 0.2.1", "chacha20", "chacha20poly1305", "crossbeam-epoch", @@ -2180,10 +2302,10 @@ dependencies = [ "socket2", "spki", "stun-format", - "thiserror", + "thiserror 1.0.58", "tokio", "tokio-tungstenite", - "tun", + "tun-rs", "windows-sys 0.59.0", "zstd", ] @@ -2231,7 +2353,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", "wasm-bindgen-shared", ] @@ -2253,7 +2375,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.93", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2285,12 +2407,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - [[package]] name = "wildmatch" version = "1.1.0" @@ -2476,6 +2592,29 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wintun-bindings" +version = "0.7.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e35d3911efde5ee25586385204127ff6a3f251477dcdd3b222775aaa4d95977" +dependencies = [ + "c2rust-bitfields", + "libloading", + "log", + "thiserror 2.0.9", + "windows-sys 0.59.0", +] + [[package]] name = "xml-rs" version = "0.8.20" diff --git a/vnt/Cargo.toml b/vnt/Cargo.toml index 6aa165e..8955582 100644 --- a/vnt/Cargo.toml +++ b/vnt/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tun = { path = "tun", optional = true } +tun-rs = { version = "1.5.0", optional = true,features = ["experimental"] } packet = { path = "./packet" } bytes = "1.5.0" log = "0.4.17" @@ -81,7 +81,7 @@ ip_proxy = [] port_mapping = [] lz4_compress = ["lz4_flex"] zstd_compress = ["zstd"] -integrated_tun = ["tun"] +integrated_tun = ["tun-rs"] upnp = ["igd"] ws = ["tokio-tungstenite"] wss = ["ws", "tokio-tungstenite/rustls-tls-native-roots", "tokio-tungstenite/rustls-tls-webpki-roots", "rustls"] \ No newline at end of file diff --git a/vnt/src/core/mod.rs b/vnt/src/core/mod.rs index 53defef..a949008 100644 --- a/vnt/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -96,15 +96,6 @@ impl Config { allow_wire_guard: bool, local_dev: Option, ) -> anyhow::Result { - #[cfg(windows)] - #[cfg(feature = "integrated_tun")] - if !tap { - if let Err(e) = tun::Device::check_tun_dll() { - log::warn!("校验平台dll {:?}", e); - Err(e)?; - } - } - for x in stun_server.iter_mut() { if !x.contains(":") { x.push_str(":3478"); diff --git a/vnt/src/handle/recv_data/server.rs b/vnt/src/handle/recv_data/server.rs index c3adf7b..c156d1e 100644 --- a/vnt/src/handle/recv_data/server.rs +++ b/vnt/src/handle/recv_data/server.rs @@ -7,12 +7,12 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use crossbeam_utils::atomic::AtomicCell; -use parking_lot::Mutex; -use protobuf::Message; - use packet::icmp::{icmp, Kind}; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; +use parking_lot::Mutex; +use protobuf::Message; +use tun_rs::AbstractDevice; use crate::channel::context::ChannelContext; use crate::channel::{Route, RouteKey}; @@ -360,10 +360,9 @@ impl ServerPacketHandler { &self.callback, ) { Ok(device) => { - use tun::device::IFace; let tun_info = crate::handle::callback::DeviceInfo::new( device.name().unwrap_or("unknown".into()), - device.version().unwrap_or("unknown".into()), + "".into(), ); log::info!("tun信息{:?}", tun_info); self.callback.create_tun(tun_info); @@ -392,7 +391,7 @@ impl ServerPacketHandler { "device_fd == 0".into(), )); } else { - match tun::Device::new(device_fd as _) { + match tun_rs::platform::Device::from_fd(device_fd as _) { Ok(device) => { if let Err(e) = self.tun_device_helper.start( Arc::new(device), diff --git a/vnt/src/handle/tun_tap/mod.rs b/vnt/src/handle/tun_tap/mod.rs index abbe944..6571e48 100644 --- a/vnt/src/handle/tun_tap/mod.rs +++ b/vnt/src/handle/tun_tap/mod.rs @@ -1,19 +1,11 @@ pub mod tun_handler; -#[cfg(unix)] -mod unix; - use crossbeam_utils::atomic::AtomicCell; use parking_lot::Mutex; use std::sync::Arc; -#[cfg(unix)] -pub(crate) use unix::*; +mod platform; -#[cfg(target_os = "windows")] -mod windows; - -#[cfg(target_os = "windows")] -pub(crate) use windows::*; +pub(crate) use platform::*; /// 仅仅是停止tun,不停止vnt #[derive(Clone, Default)] diff --git a/vnt/src/handle/tun_tap/windows.rs b/vnt/src/handle/tun_tap/platform.rs similarity index 96% rename from vnt/src/handle/tun_tap/windows.rs rename to vnt/src/handle/tun_tap/platform.rs index 3c91b56..53e8e3b 100644 --- a/vnt/src/handle/tun_tap/windows.rs +++ b/vnt/src/handle/tun_tap/platform.rs @@ -13,8 +13,7 @@ use parking_lot::Mutex; use std::collections::HashMap; use std::net::Ipv4Addr; use std::sync::Arc; -use tun::device::IFace; -use tun::Device; +use tun_rs::platform::Device; pub(crate) fn start_simple( stop_manager: StopManager, @@ -85,8 +84,7 @@ fn start_simple0( let mut buf = [0; BUFFER_SIZE]; let mut extend = [0; BUFFER_SIZE]; loop { - let len = device.read(&mut buf[12..])? + 12; - //单线程的 + let len = device.recv(&mut buf[12..])? + 12; // buf是重复利用的,需要重置头部 buf[..12].fill(0); match crate::handle::tun_tap::tun_handler::handle( diff --git a/vnt/src/handle/tun_tap/tun_handler.rs b/vnt/src/handle/tun_tap/tun_handler.rs index aa0bba7..1fd8c52 100644 --- a/vnt/src/handle/tun_tap/tun_handler.rs +++ b/vnt/src/handle/tun_tap/tun_handler.rs @@ -1,16 +1,14 @@ use crossbeam_utils::atomic::AtomicCell; +use packet::icmp::icmp::IcmpPacket; +use packet::icmp::Kind; +use packet::ip::ipv4::packet::IpV4Packet; +use packet::ip::ipv4::protocol::Protocol; use parking_lot::Mutex; use std::collections::HashMap; use std::net::Ipv4Addr; use std::sync::Arc; use std::{io, thread}; - -use packet::icmp::icmp::IcmpPacket; -use packet::icmp::Kind; -use packet::ip::ipv4::packet::IpV4Packet; -use packet::ip::ipv4::protocol::Protocol; -use tun::device::IFace; -use tun::Device; +use tun_rs::platform::Device; use crate::channel::context::ChannelContext; use crate::channel::sender::{send_to_wg, send_to_wg_broadcast}; @@ -38,7 +36,7 @@ fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> anyho ipv4_packet.set_source_ip(ipv4_packet.destination_ip()); ipv4_packet.set_destination_ip(src); ipv4_packet.update_checksum(); - device_writer.write(ipv4_packet.buffer)?; + device_writer.send(ipv4_packet.buffer)?; } } Ok(()) diff --git a/vnt/src/handle/tun_tap/unix.rs b/vnt/src/handle/tun_tap/unix.rs deleted file mode 100644 index 80d7a22..0000000 --- a/vnt/src/handle/tun_tap/unix.rs +++ /dev/null @@ -1,154 +0,0 @@ -use crate::channel::context::ChannelContext; -use crate::channel::BUFFER_SIZE; -use crate::cipher::Cipher; -use crate::compression::Compressor; -use crate::external_route::ExternalRoute; -use crate::handle::tun_tap::DeviceStop; -use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; -#[cfg(feature = "ip_proxy")] -use crate::ip_proxy::IpProxyMap; -use crate::util::StopManager; -use crossbeam_utils::atomic::AtomicCell; -use mio::event::Source; -use mio::unix::SourceFd; -use mio::{Events, Interest, Poll, Token, Waker}; -use parking_lot::Mutex; -use std::collections::HashMap; -use std::io; -use std::net::Ipv4Addr; -use std::os::fd::AsRawFd; -use std::sync::Arc; -use tun::Device; - -const STOP: Token = Token(0); -const FD: Token = Token(1); - -pub(crate) fn start_simple( - stop_manager: StopManager, - context: &ChannelContext, - device: Arc, - current_device: Arc>, - ip_route: ExternalRoute, - #[cfg(feature = "ip_proxy")] ip_proxy_map: Option, - client_cipher: Cipher, - server_cipher: Cipher, - device_map: Arc)>>, - compressor: Compressor, - device_stop: DeviceStop, - allow_wire_guard: bool, -) -> anyhow::Result<()> { - let poll = Poll::new()?; - let waker = Arc::new(Waker::new(poll.registry(), STOP)?); - let _waker = waker.clone(); - let worker = { - stop_manager.add_listener("tun_device".into(), move || { - if let Err(e) = waker.wake() { - log::warn!("{:?}", e); - } - })? - }; - let worker_cell = Arc::new(AtomicCell::new(Some(worker))); - let _worker_cell = worker_cell.clone(); - device_stop.set_stop_fn(move || { - if let Some(worker) = _worker_cell.take() { - worker.stop_self() - } - }); - if let Err(e) = start_simple0( - poll, - context, - device, - current_device, - ip_route, - #[cfg(feature = "ip_proxy")] - ip_proxy_map, - client_cipher, - server_cipher, - device_map, - compressor, - allow_wire_guard, - ) { - log::error!("{:?}", e); - }; - device_stop.stopped(); - if let Some(worker) = worker_cell.take() { - worker.stop_all(); - } - drop(_waker); - Ok(()) -} - -fn start_simple0( - mut poll: Poll, - context: &ChannelContext, - device: Arc, - current_device: Arc>, - ip_route: ExternalRoute, - #[cfg(feature = "ip_proxy")] ip_proxy_map: Option, - client_cipher: Cipher, - server_cipher: Cipher, - device_map: Arc)>>, - compressor: Compressor, - allow_wire_guard: bool, -) -> anyhow::Result<()> { - let mut buf = [0; BUFFER_SIZE]; - let mut extend = [0; BUFFER_SIZE]; - let fd = device.as_tun_fd(); - fd.set_nonblock()?; - SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?; - let mut events = Events::with_capacity(4); - #[cfg(not(target_os = "macos"))] - let start = 12; - #[cfg(target_os = "macos")] - let start = 12 - 4; - loop { - if let Err(e) = poll.poll(&mut events, None) { - crate::ignore_io_interrupted(e)?; - continue; - } - for event in events.iter() { - if event.token() == STOP { - return Ok(()); - } - let mut retries = 0; - loop { - let len = match fd.read(&mut buf[start..]) { - Ok(len) => len + start, - Err(e) => { - if e.kind() == io::ErrorKind::WouldBlock { - retries += 1; - if retries < 8 { - continue; - } - break; - } - Err(e)? - } - }; - // buf是重复利用的,需要重置头部 - buf[..12].fill(0); - match crate::handle::tun_tap::tun_handler::handle( - context, - &mut buf, - len, - &mut extend, - &device, - current_device.load(), - &ip_route, - #[cfg(feature = "ip_proxy")] - &ip_proxy_map, - &client_cipher, - &server_cipher, - &device_map, - &compressor, - allow_wire_guard, - ) { - Ok(_) => {} - Err(e) => { - log::warn!("{:?}", e) - } - } - } - } - } -} diff --git a/vnt/src/tun_tap_device/create_device.rs b/vnt/src/tun_tap_device/create_device.rs index 2514c47..64035f6 100644 --- a/vnt/src/tun_tap_device/create_device.rs +++ b/vnt/src/tun_tap_device/create_device.rs @@ -1,9 +1,10 @@ -use crate::{DeviceConfig, ErrorInfo, ErrorType, VntCallback}; use std::io; use std::net::Ipv4Addr; use std::sync::Arc; -use tun::device::IFace; -use tun::Device; +use tun_rs::platform::Device; +use tun_rs::AbstractDevice; + +use crate::{DeviceConfig, ErrorInfo, ErrorType, VntCallback}; #[cfg(any(target_os = "windows", target_os = "linux"))] const DEFAULT_TUN_NAME: &str = "vnt-tun"; @@ -23,30 +24,24 @@ pub fn create_device( )); } }; - if let Err(e) = device.set_ip(config.virtual_ip, config.virtual_netmask) { - log::error!("LocalIpExists {:?}", e); - return Err(ErrorInfo::new_msg( - ErrorType::LocalIpExists, - format!("set_ip {:?}", e), - )); - } - if let Err(e) = device.add_route(config.virtual_network, config.virtual_netmask, 1) { - log::warn!("添加默认路由失败 ={:?}", e); - } - if let Err(e) = device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, 1) { + #[cfg(windows)] + let index = device.if_index().unwrap(); + #[cfg(unix)] + let index = &device.name().unwrap(); + if let Err(e) = add_route(index, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST) { log::warn!("添加广播路由失败 ={:?}", e); } - if let Err(e) = device.add_route( + if let Err(e) = add_route( + index, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), - 1, ) { log::warn!("添加组播路由失败 ={:?}", e); } for (dest, mask) in config.external_route { - if let Err(e) = device.add_route(dest, mask, 1) { + if let Err(e) = add_route(index, dest, mask) { log::warn!("添加路由失败,请检查-i参数是否和现有路由冲突 ={:?}", e); call.error(ErrorInfo::new_msg( ErrorType::Warn, @@ -61,14 +56,29 @@ pub fn create_device( } fn create_device0(config: &DeviceConfig) -> io::Result> { + let mut tun_config = tun_rs::Configuration::default(); + let netmask = u32::from_be_bytes(config.virtual_netmask.octets()); + tun_config + .address_with_prefix(config.virtual_ip, netmask.count_ones() as u8) + .up(); #[cfg(target_os = "windows")] - let default_name: &str = if config.tap { - DEFAULT_TAP_NAME - } else { - DEFAULT_TUN_NAME - }; + { + let default_name = if config.tap { + tun_config.layer(tun_rs::Layer::L2); + DEFAULT_TAP_NAME + } else { + DEFAULT_TUN_NAME + }; + tun_config.name( + config + .device_name + .clone() + .unwrap_or(default_name.to_string()), + ); + } + #[cfg(target_os = "linux")] - let device = { + { let device_name = config .device_name .clone() @@ -76,20 +86,11 @@ fn create_device0(config: &DeviceConfig) -> io::Result> { if &device_name == DEFAULT_TUN_NAME { delete_device(DEFAULT_TUN_NAME); } - Arc::new(Device::new(Some(device_name))?) - }; - #[cfg(target_os = "macos")] - let device = Arc::new(Device::new(config.device_name.clone())?); - #[cfg(target_os = "windows")] - let device = Arc::new(Device::new( - config - .device_name - .clone() - .unwrap_or(default_name.to_string()), - config.tap, - )?); - device.set_mtu(config.mtu)?; - Ok(device) + } + + tun_config.mtu(config.mtu as u16); + let device = tun_rs::create(&tun_config)?; + Ok(Arc::new(device)) } #[cfg(target_os = "linux")] @@ -106,3 +107,76 @@ fn delete_device(name: &str) { log::warn!("删除网卡失败:{:?}", delete_tun); } } + +#[cfg(target_os = "windows")] +pub fn add_route(index: u32, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { + let cmd = format!( + "route add {:?} mask {:?} {:?} metric {} if {}", + dest, + netmask, + Ipv4Addr::UNSPECIFIED, + 1, + index + ); + exe_cmd(&cmd) +} +#[cfg(target_os = "windows")] +pub fn exe_cmd(cmd: &str) -> io::Result<()> { + use std::os::windows::process::CommandExt; + + println!("exe cmd: {}", cmd); + let out = std::process::Command::new("cmd") + .creation_flags(windows_sys::Win32::System::Threading::CREATE_NO_WINDOW) + .arg("/C") + .arg(&cmd) + .output()?; + if !out.status.success() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("cmd={},out={:?}", cmd, String::from_utf8(out.stderr)), + )); + } + Ok(()) +} + +#[cfg(target_os = "macos")] +pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { + let cmd = format!( + "route -n add {} -netmask {} -interface {}", + address, netmask, name + ); + exe_cmd(&cmd)?; + Ok(()) +} +#[cfg(target_os = "linux")] +pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { + let cmd = if netmask.is_broadcast() { + format!("route add -host {:?} {}", address, name) + } else { + format!( + "route add -net {}/{} {}", + address, + u32::from(netmask).count_ones(), + name + ) + }; + exe_cmd(&cmd)?; + Ok(()) +} +#[cfg(any(target_os = "macos", target_os = "linux"))] +pub fn exe_cmd(cmd: &str) -> io::Result { + use std::process::Command; + println!("exe cmd: {}", cmd); + let out = Command::new("sh") + .arg("-c") + .arg(cmd) + .output() + .expect("sh exec error!"); + if !out.status.success() { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("cmd={},out={:?}", cmd, out), + )); + } + Ok(out) +} diff --git a/vnt/src/tun_tap_device/tun_create_helper.rs b/vnt/src/tun_tap_device/tun_create_helper.rs index 12d1b1b..b4026d2 100644 --- a/vnt/src/tun_tap_device/tun_create_helper.rs +++ b/vnt/src/tun_tap_device/tun_create_helper.rs @@ -3,12 +3,6 @@ use std::io; use std::net::Ipv4Addr; use std::sync::Arc; -use crossbeam_utils::atomic::AtomicCell; -use parking_lot::Mutex; - -use tun::device::IFace; -use tun::Device; - use crate::channel::context::ChannelContext; use crate::cipher::Cipher; use crate::compression::Compressor; @@ -19,6 +13,9 @@ use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::ip_proxy::IpProxyMap; use crate::tun_tap_device::vnt_device::DeviceWrite; use crate::util::StopManager; +use crossbeam_utils::atomic::AtomicCell; +use parking_lot::Mutex; +use tun_rs::platform::Device; #[repr(transparent)] #[derive(Clone, Default)] @@ -41,7 +38,7 @@ impl DeviceWrite for DeviceAdapter { #[inline] fn write(&self, buf: &[u8]) -> io::Result { if let Some(tun) = self.tun.lock().as_ref() { - tun.write(buf) + tun.send(buf) } else { Err(io::Error::new(io::ErrorKind::NotFound, "not tun device")) } diff --git a/vnt/tun/Cargo.toml b/vnt/tun/Cargo.toml deleted file mode 100644 index 0e56282..0000000 --- a/vnt/tun/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "tun" -version = "0.1.0" -edition = "2021" - - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -libc = "0.2.153" - -log = { version = "0.4.20", features = [] } -rand = "0.8.5" -sha2 = { version = "0.10.6", features = ["oid"] } - -[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] -ioctl = { version = "0.8", package = "ioctl-sys" } - -[target.'cfg(target_os = "windows")'.dependencies] -libloading = "0.8.0" -widestring = "1.0.2" -winapi = { version = "0.3", features = [ - "errhandlingapi", - "libloaderapi", - "combaseapi", - "ioapiset", - "winioctl", - "setupapi", - "synchapi", - "netioapi", - "fileapi", "handleapi", "winerror", "minwindef", "ifdef", "basetsd", "winnt", "winreg", "winbase", "minwinbase", - "impl-default" -] } - diff --git a/vnt/tun/src/android/mod.rs b/vnt/tun/src/android/mod.rs deleted file mode 100644 index 79f78b9..0000000 --- a/vnt/tun/src/android/mod.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::device::IFace; -use crate::Fd; -use std::io; -use std::net::Ipv4Addr; -use std::os::fd::RawFd; - -pub struct Device { - fd: Fd, -} - -impl Device { - pub fn new(fd: RawFd) -> io::Result { - Ok(Self { fd: Fd::new(fd)? }) - } -} -impl Device { - pub fn as_tun_fd(&self) -> &Fd { - &self.fd - } -} -impl IFace for Device { - fn version(&self) -> io::Result { - Ok(String::new()) - } - - fn name(&self) -> io::Result { - Ok(String::new()) - } - - fn shutdown(&self) -> io::Result<()> { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn set_ip(&self, _address: Ipv4Addr, _mask: Ipv4Addr) -> io::Result<()> { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn mtu(&self) -> io::Result { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn set_mtu(&self, _value: u32) -> io::Result<()> { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn add_route(&self, _dest: Ipv4Addr, _netmask: Ipv4Addr, _metric: u16) -> io::Result<()> { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn delete_route(&self, _dest: Ipv4Addr, _netmask: Ipv4Addr) -> io::Result<()> { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - self.fd.read(buf) - } - - fn write(&self, buf: &[u8]) -> io::Result { - self.fd.write(buf) - } -} diff --git a/vnt/tun/src/device.rs b/vnt/tun/src/device.rs deleted file mode 100644 index d1a71b3..0000000 --- a/vnt/tun/src/device.rs +++ /dev/null @@ -1,24 +0,0 @@ -use io::Result; -use std::io; -use std::net::Ipv4Addr; - -pub trait IFace { - fn version(&self) -> Result; - /// Get the device name. - fn name(&self) -> Result; - - fn shutdown(&self) -> Result<()>; - - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> Result<()>; - - /// Get the MTU. - fn mtu(&self) -> Result; - - /// Set the MTU. - fn set_mtu(&self, value: u32) -> Result<()>; - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, metric: u16) -> Result<()>; - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> Result<()>; - - fn read(&self, buf: &mut [u8]) -> Result; - fn write(&self, buf: &[u8]) -> Result; -} diff --git a/vnt/tun/src/lib.rs b/vnt/tun/src/lib.rs deleted file mode 100644 index b597a48..0000000 --- a/vnt/tun/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -/// 参考 -/// https://github.com/meh/rust-tun -/// https://github.com/Tazdevil971/tap-windows -/// https://github.com/nulldotblack/wintun -pub mod device; - -#[cfg(target_os = "linux")] -mod linux; -#[cfg(target_os = "linux")] -pub use linux::Device; - -#[cfg(target_os = "android")] -mod android; -#[cfg(target_os = "android")] -pub use android::Device; - -#[cfg(target_os = "macos")] -mod macos; -#[cfg(target_os = "macos")] -pub use macos::Device; - -#[cfg(unix)] -mod unix; -#[cfg(unix)] -pub use unix::Fd; -#[cfg(windows)] -mod windows; - -#[cfg(windows)] -pub use windows::Device; - -#[cfg(windows)] -mod packet; diff --git a/vnt/tun/src/linux/device.rs b/vnt/tun/src/linux/device.rs deleted file mode 100644 index a90a176..0000000 --- a/vnt/tun/src/linux/device.rs +++ /dev/null @@ -1,281 +0,0 @@ -#![allow(dead_code)] -use std::ffi::{CStr, CString}; -use std::net::Ipv4Addr; -use std::os::fd::AsRawFd; -use std::{io, mem, ptr}; - -use libc::{ - c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_TUN, IFF_UP, - IFNAMSIZ, O_RDWR, SOCK_DGRAM, -}; - -use crate::device::IFace; -use crate::linux::route; -use crate::linux::sys::*; -use crate::unix::{exe_cmd, Fd, SockAddr}; - -pub struct Device { - name: String, - ctl: Fd, - tun: Fd, -} - -impl Device { - pub fn new(name: Option) -> io::Result { - let device = unsafe { - let dev = match name { - Some(name) => { - let name = - CString::new(name).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - - if name.as_bytes_with_nul().len() > IFNAMSIZ { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "name too long")); - } - - Some(name) - } - - None => None, - }; - - let mut req: ifreq = mem::zeroed(); - - if let Some(dev) = dev.as_ref() { - ptr::copy_nonoverlapping( - dev.as_ptr() as *const c_char, - req.ifr_name.as_mut_ptr(), - dev.as_bytes().len(), - ); - } - - let device_type: c_short = IFF_TUN as c_short; //if tap { IFF_TAP } else { IFF_TUN } as c_short; - - let queues_num = 1; - - let iff_no_pi = IFF_NO_PI as c_short; - let iff_multi_queue = IFF_MULTI_QUEUE as c_short; - let packet_information = false; - req.ifr_ifru.ifru_flags = device_type - | if packet_information { 0 } else { iff_no_pi } - | if queues_num > 1 { iff_multi_queue } else { 0 }; - - let tun = Fd::new(libc::open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR)) - .map_err(|_| io::Error::last_os_error())?; - - if tunsetiff(tun.0, &mut req as *mut _ as *mut _) < 0 { - return Err(io::Error::last_os_error()); - } - - let ctl = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0))?; - - let name = CStr::from_ptr(req.ifr_name.as_ptr()) - .to_string_lossy() - .to_string(); - let set_txqueuelen = format!("ifconfig {} txqueuelen 1000", name); - if let Err(e) = exe_cmd(&set_txqueuelen) { - log::warn!("{:?}", e); - } - Device { name, tun, ctl } - }; - device.enabled(true)?; - Ok(device) - } -} - -impl Device { - fn enabled(&self, value: bool) -> io::Result<()> { - unsafe { - let mut req = self.request(); - - if siocgifflags(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - if value { - req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short; - } else { - req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short); - } - - if siocsifflags(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - unsafe fn request(&self) -> ifreq { - let mut req: ifreq = mem::zeroed(); - ptr::copy_nonoverlapping( - self.name.as_ptr() as *const c_char, - req.ifr_name.as_mut_ptr(), - self.name.len(), - ); - req - } - fn address(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error().into()); - } - - SockAddr::new(&req.ifr_ifru.ifru_addr).map(Into::into) - } - } - - fn set_address(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifr_ifru.ifru_addr = SockAddr::from(value).into(); - - if siocsifaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn destination(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifr_ifru.ifru_dstaddr).map(Into::into) - } - } - - fn set_destination(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifr_ifru.ifru_dstaddr = SockAddr::from(value).into(); - - if siocsifdstaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn broadcast(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifr_ifru.ifru_broadaddr).map(Into::into) - } - } - - fn set_broadcast(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifr_ifru.ifru_broadaddr = SockAddr::from(value).into(); - - if siocsifbrdaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn netmask(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifnetmask(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifr_ifru.ifru_netmask).map(Into::into) - } - } - - fn set_netmask(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifr_ifru.ifru_netmask = SockAddr::from(value).into(); - - if siocsifnetmask(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } -} - -impl Device { - pub fn as_tun_fd(&self) -> &Fd { - &self.tun - } -} - -impl IFace for Device { - fn version(&self) -> io::Result { - Ok(String::new()) - } - - fn name(&self) -> io::Result { - Ok(self.name.clone()) - } - - fn shutdown(&self) -> io::Result<()> { - exe_cmd(&format!("ip link delete {}", self.name))?; - Ok(()) - } - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> { - self.set_address(address)?; - self.set_netmask(mask) - } - - fn mtu(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifmtu(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(req.ifr_ifru.ifru_mtu as u32) - } - } - - fn set_mtu(&self, value: u32) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifr_ifru.ifru_mtu = value as _; - - if siocsifmtu(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, _metric: u16) -> io::Result<()> { - route::add_route(&self.name, dest, netmask) - } - - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - route::del_route(&self.name, dest, netmask) - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - self.tun.read(buf) - } - - fn write(&self, buf: &[u8]) -> io::Result { - self.tun.write(buf) - } -} diff --git a/vnt/tun/src/linux/mod.rs b/vnt/tun/src/linux/mod.rs deleted file mode 100644 index 8e8dcc6..0000000 --- a/vnt/tun/src/linux/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod device; -pub use device::Device; -mod route; -mod sys; diff --git a/vnt/tun/src/linux/route.rs b/vnt/tun/src/linux/route.rs deleted file mode 100644 index b6c1630..0000000 --- a/vnt/tun/src/linux/route.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::io; -use std::net::Ipv4Addr; - -use crate::unix::exe_cmd; - -pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - let cmd = if netmask.is_broadcast() { - format!("route add -host {:?} {}", address, name) - } else { - format!( - "route add -net {}/{} {}", - address, - u32::from(netmask).count_ones(), - name - ) - }; - exe_cmd(&cmd)?; - Ok(()) -} - -pub fn del_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - let cmd = format!("ip route del {:?}/{:?} dev {}", address, netmask, name); - exe_cmd(&cmd)?; - Ok(()) -} diff --git a/vnt/tun/src/linux/sys.rs b/vnt/tun/src/linux/sys.rs deleted file mode 100644 index 0913dda..0000000 --- a/vnt/tun/src/linux/sys.rs +++ /dev/null @@ -1,21 +0,0 @@ -use ioctl::*; -use libc::{c_int, ifreq}; - -ioctl!(bad read siocgifflags with 0x8913; ifreq); -ioctl!(bad write siocsifflags with 0x8914; ifreq); -ioctl!(bad read siocgifaddr with 0x8915; ifreq); -ioctl!(bad write siocsifaddr with 0x8916; ifreq); -ioctl!(bad read siocgifdstaddr with 0x8917; ifreq); -ioctl!(bad write siocsifdstaddr with 0x8918; ifreq); -ioctl!(bad read siocgifbrdaddr with 0x8919; ifreq); -ioctl!(bad write siocsifbrdaddr with 0x891a; ifreq); -ioctl!(bad read siocgifnetmask with 0x891b; ifreq); -ioctl!(bad write siocsifnetmask with 0x891c; ifreq); -ioctl!(bad read siocgifmtu with 0x8921; ifreq); -ioctl!(bad write siocsifmtu with 0x8922; ifreq); -ioctl!(bad write siocsifname with 0x8923; ifreq); - -ioctl!(write tunsetiff with b'T', 202; c_int); -ioctl!(write tunsetpersist with b'T', 203; c_int); -ioctl!(write tunsetowner with b'T', 204; c_int); -ioctl!(write tunsetgroup with b'T', 206; c_int); diff --git a/vnt/tun/src/macos/device.rs b/vnt/tun/src/macos/device.rs deleted file mode 100644 index b7d70eb..0000000 --- a/vnt/tun/src/macos/device.rs +++ /dev/null @@ -1,297 +0,0 @@ -#![allow(dead_code)] -use std::ffi::{c_void, CStr}; -use std::net::Ipv4Addr; -use std::os::fd::AsRawFd; -use std::{io, mem, ptr}; - -use libc::{ - c_char, c_short, c_uint, sockaddr, socklen_t, AF_INET, AF_SYSTEM, AF_SYS_CONTROL, IFF_RUNNING, - IFF_UP, IFNAMSIZ, PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, -}; - -use crate::device::IFace; -use crate::macos::route; -use crate::macos::sys::*; -use crate::unix::{Fd, SockAddr}; - -pub struct Device { - name: String, - ctl: Fd, - tun: Fd, -} - -impl Device { - pub fn new(name: Option) -> io::Result { - let id = if let Some(name) = name { - if name.len() > IFNAMSIZ { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "name too long")); - } - - if !name.starts_with("utun") { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid name")); - } - - name[4..] - .parse::() - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))? - + 1u32 - } else { - 0u32 - }; - let device = unsafe { - let tun = Fd::new(libc::socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL))?; - - let mut info = ctl_info { - ctl_id: 0, - ctl_name: { - let mut buffer = [0; 96]; - for (i, o) in UTUN_CONTROL_NAME.as_bytes().iter().zip(buffer.iter_mut()) { - *o = *i as _; - } - buffer - }, - }; - - if ctliocginfo(tun.0, &mut info as *mut _ as *mut _) < 0 { - return Err(io::Error::last_os_error()); - } - - let addr = sockaddr_ctl { - sc_id: info.ctl_id, - sc_len: mem::size_of::() as _, - sc_family: AF_SYSTEM as _, - ss_sysaddr: AF_SYS_CONTROL as _, - sc_unit: id as c_uint, - sc_reserved: [0; 5], - }; - - let address = &addr as *const sockaddr_ctl as *const sockaddr; - if libc::connect(tun.0, address, mem::size_of_val(&addr) as socklen_t) < 0 { - return Err(io::Error::last_os_error()); - } - - let mut name = [0u8; 64]; - let mut name_len: socklen_t = 64; - - let optval = &mut name as *mut _ as *mut c_void; - let optlen = &mut name_len as *mut socklen_t; - if libc::getsockopt(tun.0, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, optval, optlen) < 0 { - return Err(io::Error::last_os_error()); - } - - let ctl = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0))?; - - Device { - name: CStr::from_ptr(name.as_ptr() as *const c_char) - .to_string_lossy() - .into(), - tun, - ctl, - } - }; - device.enabled(true)?; - Ok(device) - } -} - -impl Device { - fn enabled(&self, value: bool) -> io::Result<()> { - unsafe { - let mut req = self.request(); - - if siocgifflags(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - if value { - req.ifru.flags |= (IFF_UP | IFF_RUNNING) as c_short; - } else { - req.ifru.flags &= !(IFF_UP as c_short); - } - - if siocsifflags(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - unsafe fn request(&self) -> ifreq { - let mut req: ifreq = mem::zeroed(); - ptr::copy_nonoverlapping( - self.name.as_ptr() as *const c_char, - req.ifrn.name.as_mut_ptr(), - self.name.len(), - ); - req - } - fn address(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifru.addr).map(Into::into) - } - } - - fn set_address(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifru.addr = SockAddr::from(value).into(); - - if siocsifaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn destination(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifru.dstaddr).map(Into::into) - } - } - - fn set_destination(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifru.dstaddr = SockAddr::from(value).into(); - - if siocsifdstaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn broadcast(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::new(&req.ifru.broadaddr).map(Into::into) - } - } - - fn set_broadcast(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifru.broadaddr = SockAddr::from(value).into(); - - if siocsifbrdaddr(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn netmask(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifnetmask(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - SockAddr::unchecked(&req.ifru.addr).map(Into::into) - } - } - - fn set_netmask(&self, value: Ipv4Addr) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifru.addr = SockAddr::from(value).into(); - - if siocsifnetmask(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } -} -impl Device { - pub fn as_tun_fd(&self) -> &Fd { - &self.tun - } -} - -impl IFace for Device { - fn version(&self) -> io::Result { - Ok(String::new()) - } - - fn name(&self) -> io::Result { - Ok(self.name.clone()) - } - - fn shutdown(&self) -> io::Result<()> { - Ok(()) - } - - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> { - self.set_address(address)?; - self.set_netmask(mask) - } - - fn mtu(&self) -> io::Result { - unsafe { - let mut req = self.request(); - - if siocgifmtu(self.ctl.as_raw_fd(), &mut req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(req.ifru.mtu as _) - } - } - - fn set_mtu(&self, value: u32) -> io::Result<()> { - unsafe { - let mut req = self.request(); - req.ifru.mtu = value as _; - - if siocsifmtu(self.ctl.as_raw_fd(), &req) < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(()) - } - } - - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, _metric: u16) -> io::Result<()> { - route::add_route(&self.name, dest, netmask) - } - - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - route::del_route(&self.name, dest, netmask) - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - self.tun.read(buf) - } - - fn write(&self, buf: &[u8]) -> io::Result { - let mut packet = Vec::::with_capacity(4 + buf.len()); - packet.push(0); - packet.push(0); - packet.extend_from_slice(&(libc::PF_INET as u16).to_be_bytes()); - packet.extend_from_slice(buf); - self.tun.write(&packet) - } -} diff --git a/vnt/tun/src/macos/mod.rs b/vnt/tun/src/macos/mod.rs deleted file mode 100644 index 2a7a0fe..0000000 --- a/vnt/tun/src/macos/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod device; -pub use device::Device; -mod sys; - -mod route; diff --git a/vnt/tun/src/macos/route.rs b/vnt/tun/src/macos/route.rs deleted file mode 100644 index d4644b1..0000000 --- a/vnt/tun/src/macos/route.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::unix::exe_cmd; -use std::io; -use std::net::Ipv4Addr; - -pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - let cmd = format!( - "route -n add {} -netmask {} -interface {}", - address, netmask, name - ); - exe_cmd(&cmd)?; - Ok(()) -} -pub fn del_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - let cmd = format!( - "route -n delete {} -netmask {} -interface {}", - address, netmask, name - ); - exe_cmd(&cmd)?; - Ok(()) -} diff --git a/vnt/tun/src/macos/sys.rs b/vnt/tun/src/macos/sys.rs deleted file mode 100644 index ae42318..0000000 --- a/vnt/tun/src/macos/sys.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! Bindings to internal macOS stuff. - -use ioctl::*; -use libc::{c_char, c_int, c_short, c_uint, c_ushort, c_void, sockaddr, IFNAMSIZ}; - -pub const UTUN_CONTROL_NAME: &str = "com.apple.net.utun_control"; - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ctl_info { - pub ctl_id: c_uint, - pub ctl_name: [c_char; 96], -} - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct sockaddr_ctl { - pub sc_len: c_char, - pub sc_family: c_char, - pub ss_sysaddr: c_ushort, - pub sc_id: c_uint, - pub sc_unit: c_uint, - pub sc_reserved: [c_uint; 5], -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifrn { - pub name: [c_char; IFNAMSIZ], -} - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ifdevmtu { - pub current: c_int, - pub min: c_int, - pub max: c_int, -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifku { - pub ptr: *mut c_void, - pub value: c_int, -} - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ifkpi { - pub module_id: c_uint, - pub type_: c_uint, - pub ifku: ifku, -} - -#[repr(C)] -#[derive(Copy, Clone)] -pub union ifru { - pub addr: sockaddr, - pub dstaddr: sockaddr, - pub broadaddr: sockaddr, - - pub flags: c_short, - pub metric: c_int, - pub mtu: c_int, - pub phys: c_int, - pub media: c_int, - pub intval: c_int, - pub data: *mut c_void, - pub devmtu: ifdevmtu, - pub wake_flags: c_uint, - pub route_refcnt: c_uint, - pub cap: [c_int; 2], - pub functional_type: c_uint, -} - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ifreq { - pub ifrn: ifrn, - pub ifru: ifru, -} - -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ifaliasreq { - pub ifran: [c_char; IFNAMSIZ], - pub addr: sockaddr, - pub broadaddr: sockaddr, - pub mask: sockaddr, -} - -ioctl!(readwrite ctliocginfo with 'N', 3; ctl_info); - -ioctl!(write siocsifflags with 'i', 16; ifreq); -ioctl!(readwrite siocgifflags with 'i', 17; ifreq); - -ioctl!(write siocsifaddr with 'i', 12; ifreq); -ioctl!(readwrite siocgifaddr with 'i', 33; ifreq); - -ioctl!(write siocsifdstaddr with 'i', 14; ifreq); -ioctl!(readwrite siocgifdstaddr with 'i', 34; ifreq); - -ioctl!(write siocsifbrdaddr with 'i', 19; ifreq); -ioctl!(readwrite siocgifbrdaddr with 'i', 35; ifreq); - -ioctl!(write siocsifnetmask with 'i', 22; ifreq); -ioctl!(readwrite siocgifnetmask with 'i', 37; ifreq); - -ioctl!(write siocsifmtu with 'i', 52; ifreq); -ioctl!(readwrite siocgifmtu with 'i', 51; ifreq); - -ioctl!(write siocaifaddr with 'i', 26; ifaliasreq); -ioctl!(write siocdifaddr with 'i', 25; ifreq); diff --git a/vnt/tun/src/packet/arp/mod.rs b/vnt/tun/src/packet/arp/mod.rs deleted file mode 100644 index edb43db..0000000 --- a/vnt/tun/src/packet/arp/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod packet; diff --git a/vnt/tun/src/packet/arp/packet.rs b/vnt/tun/src/packet/arp/packet.rs deleted file mode 100644 index a2c96cd..0000000 --- a/vnt/tun/src/packet/arp/packet.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![allow(dead_code)] -use std::{fmt, io}; - -/// 地址解析协议,由IP地址找到MAC地址 -/// https://www.ietf.org/rfc/rfc6747.txt -/* - 0 2 4 5 6 8 10 (字节) - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 硬件类型|协议类型|硬件地址长度|协议地址长度|操作类型| - | 源MAC地址 | 源ip地址 | - | 目的MAC地址 | 目的ip地址 | -*/ - -pub struct ArpPacket { - buffer: B, -} - -impl> ArpPacket { - pub fn unchecked(buffer: B) -> Self { - Self { buffer } - } - pub fn new(buffer: B) -> io::Result { - if buffer.as_ref().len() != 28 { - Err(io::Error::from(io::ErrorKind::InvalidData))?; - } - let packet = Self::unchecked(buffer); - Ok(packet) - } -} - -impl> ArpPacket { - /// 硬件类型 以太网类型为1 - pub fn hardware_type(&self) -> u16 { - u16::from_be_bytes(self.buffer.as_ref()[0..2].try_into().unwrap()) - } - /// 上层协议类型,ipv4是0x0800 - pub fn protocol_type(&self) -> u16 { - u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap()) - } - /// 如果是MAC地址 则长度为6 - pub fn hardware_size(&self) -> u8 { - self.buffer.as_ref()[4] - } - /// 如果是IPv4 则长度为4 - pub fn protocol_size(&self) -> u8 { - self.buffer.as_ref()[5] - } - /// 操作类型,请求和响应 1:ARP请求,2:ARP响应,3:RARP请求,4:RARP响应 - pub fn op_code(&self) -> u16 { - u16::from_be_bytes(self.buffer.as_ref()[6..8].try_into().unwrap()) - } - /// 发送端硬件地址,仅支持以太网 - pub fn sender_hardware_addr(&self) -> &[u8] { - &self.buffer.as_ref()[8..14] - } - /// 发送端协议地址,仅支持IPv4 - pub fn sender_protocol_addr(&self) -> &[u8] { - &self.buffer.as_ref()[14..18] - } - /// 接收端硬件地址,仅支持以太网 - pub fn target_hardware_addr(&self) -> &[u8] { - &self.buffer.as_ref()[18..24] - } - /// 接收端协议地址,仅支持IPv4 - pub fn target_protocol_addr(&self) -> &[u8] { - &self.buffer.as_ref()[24..28] - } -} - -impl + AsMut<[u8]>> ArpPacket { - /// 硬件类型 以太网类型为1 - pub fn set_hardware_type(&mut self, value: u16) { - self.buffer.as_mut()[0..2].copy_from_slice(&value.to_be_bytes()) - } - /// 上层协议类型,ipv4是0x0800 - pub fn set_protocol_type(&mut self, value: u16) { - self.buffer.as_mut()[2..4].copy_from_slice(&value.to_be_bytes()) - } - /// 如果是MAC地址 则长度为6 - pub fn set_hardware_size(&mut self, value: u8) { - self.buffer.as_mut()[4] = value - } - /// 如果是IPv4 则长度为4 - pub fn set_protocol_size(&mut self, value: u8) { - self.buffer.as_mut()[5] = value - } - /// 操作类型,请求和响应 1:ARP请求,2:ARP响应,3:RARP请求,4:RARP响应 - pub fn set_op_code(&mut self, value: u16) { - self.buffer.as_mut()[6..8].copy_from_slice(&value.to_be_bytes()) - } - /// 发送端硬件地址,仅支持以太网 - pub fn set_sender_hardware_addr(&mut self, buf: &[u8]) { - self.buffer.as_mut()[8..14].copy_from_slice(buf) - } - /// 发送端协议地址,仅支持IPv4 - pub fn set_sender_protocol_addr(&mut self, buf: &[u8]) { - self.buffer.as_mut()[14..18].copy_from_slice(buf) - } - /// 接收端硬件地址,仅支持以太网 - pub fn set_target_hardware_addr(&mut self, buf: &[u8]) { - self.buffer.as_mut()[18..24].copy_from_slice(buf) - } - /// 接收端协议地址,仅支持IPv4 - pub fn set_target_protocol_addr(&mut self, buf: &[u8]) { - self.buffer.as_mut()[24..28].copy_from_slice(buf) - } -} - -impl> fmt::Debug for ArpPacket { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ArpPacket") - .field("hardware_type", &self.hardware_type()) - .field("protocol_type", &self.protocol_type()) - .field("hardware_size", &self.hardware_size()) - .field("protocol_size", &self.protocol_size()) - .field("op_code", &self.op_code()) - .field("sender_hardware_addr", &self.sender_hardware_addr()) - .field("sender_protocol_addr", &self.sender_protocol_addr()) - .field("target_hardware_addr", &self.target_hardware_addr()) - .field("target_protocol_addr", &self.target_protocol_addr()) - .finish() - } -} diff --git a/vnt/tun/src/packet/ethernet/mod.rs b/vnt/tun/src/packet/ethernet/mod.rs deleted file mode 100644 index c9cf115..0000000 --- a/vnt/tun/src/packet/ethernet/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod packet; -pub mod protocol; diff --git a/vnt/tun/src/packet/ethernet/packet.rs b/vnt/tun/src/packet/ethernet/packet.rs deleted file mode 100644 index a3f7460..0000000 --- a/vnt/tun/src/packet/ethernet/packet.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::packet::ethernet::protocol::Protocol; -use std::{fmt, io}; - -/// 以太网帧协议 -/// https://www.ietf.org/rfc/rfc894.txt -/* - 0 6 12 14 (字节) - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 目的地址 | 源地址 | 类型 | -*/ -pub struct EthernetPacket { - pub buffer: B, -} - -impl> EthernetPacket { - pub fn unchecked(buffer: B) -> EthernetPacket { - EthernetPacket { buffer } - } - - pub fn new(buffer: B) -> io::Result> { - let packet = EthernetPacket::unchecked(buffer); - //头部固定14位 - if packet.buffer.as_ref().len() < 14 { - Err(io::Error::new( - io::ErrorKind::InvalidData, - format!("len={}", packet.buffer.as_ref().len()), - ))?; - } - - Ok(packet) - } -} - -impl> EthernetPacket { - /// 目的MAC地址 - pub fn destination(&self) -> &[u8] { - &self.buffer.as_ref()[0..6] - } - /// 源MAC地址 - pub fn source(&self) -> &[u8] { - &self.buffer.as_ref()[6..12] - } - /// 3层协议 - pub fn protocol(&self) -> Protocol { - u16::from_be_bytes(self.buffer.as_ref()[12..14].try_into().unwrap()).into() - } - /// 载荷 - pub fn payload(&self) -> &[u8] { - &self.buffer.as_ref()[14..] - } -} - -impl + AsMut<[u8]>> EthernetPacket { - pub fn set_destination(&mut self, value: &[u8]) { - self.buffer.as_mut()[0..6].copy_from_slice(value); - } - - pub fn set_source(&mut self, value: &[u8]) { - self.buffer.as_mut()[6..12].copy_from_slice(value); - } - - pub fn set_protocol(&mut self, value: Protocol) { - let p: u16 = value.into(); - self.buffer.as_mut()[12..14].copy_from_slice(&p.to_be_bytes()) - } - pub fn payload_mut(&mut self) -> &mut [u8] { - &mut self.buffer.as_mut()[14..] - } -} - -impl> fmt::Debug for EthernetPacket { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("EthernetPacket") - .field("destination", &self.destination()) - .field("source", &self.source()) - .field("protocol", &self.protocol()) - .field("payload", &self.payload()) - .finish() - } -} diff --git a/vnt/tun/src/packet/ethernet/protocol.rs b/vnt/tun/src/packet/ethernet/protocol.rs deleted file mode 100644 index e775a28..0000000 --- a/vnt/tun/src/packet/ethernet/protocol.rs +++ /dev/null @@ -1,141 +0,0 @@ -/// 以太网帧协议 -#[derive(Eq, PartialEq, Copy, Clone, Debug)] -pub enum Protocol { - /// - Ipv4, - - /// - Arp, - - /// - WakeOnLan, - - /// - Trill, - - /// - DecNet, - - /// - Rarp, - - /// - AppleTalk, - - /// - Aarp, - - /// - Ipx, - - /// - Qnx, - - /// - Ipv6, - - /// - FlowControl, - - /// - CobraNet, - - /// - Mpls, - - /// - MplsMulticast, - - /// - PppoeDiscovery, - - /// - PppoeSession, - - /// - Vlan, - - /// - PBridge, - - /// - Lldp, - - /// - Ptp, - - /// - Cfm, - - /// - QinQ, - - /// - Unknown(u16), -} - -impl From for Protocol { - fn from(value: u16) -> Protocol { - use self::Protocol::*; - - match value { - 0x0800 => Ipv4, - 0x0806 => Arp, - 0x0842 => WakeOnLan, - 0x22f3 => Trill, - 0x6003 => DecNet, - 0x8035 => Rarp, - 0x809b => AppleTalk, - 0x80f3 => Aarp, - 0x8137 => Ipx, - 0x8204 => Qnx, - 0x86dd => Ipv6, - 0x8808 => FlowControl, - 0x8819 => CobraNet, - 0x8847 => Mpls, - 0x8848 => MplsMulticast, - 0x8863 => PppoeDiscovery, - 0x8864 => PppoeSession, - 0x8100 => Vlan, - 0x88a8 => PBridge, - 0x88cc => Lldp, - 0x88f7 => Ptp, - 0x8902 => Cfm, - 0x9100 => QinQ, - n => Unknown(n), - } - } -} - -impl Into for Protocol { - fn into(self) -> u16 { - use self::Protocol::*; - - match self { - Ipv4 => 0x0800, - Arp => 0x0806, - WakeOnLan => 0x0842, - Trill => 0x22f3, - DecNet => 0x6003, - Rarp => 0x8035, - AppleTalk => 0x809b, - Aarp => 0x80f3, - Ipx => 0x8137, - Qnx => 0x8204, - Ipv6 => 0x86dd, - FlowControl => 0x8808, - CobraNet => 0x8819, - Mpls => 0x8847, - MplsMulticast => 0x8848, - PppoeDiscovery => 0x8863, - PppoeSession => 0x8864, - Vlan => 0x8100, - PBridge => 0x88a8, - Lldp => 0x88cc, - Ptp => 0x88f7, - Cfm => 0x8902, - QinQ => 0x9100, - Unknown(n) => n, - } - } -} diff --git a/vnt/tun/src/packet/mod.rs b/vnt/tun/src/packet/mod.rs deleted file mode 100644 index aee2cf1..0000000 --- a/vnt/tun/src/packet/mod.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::packet::ethernet::protocol::Protocol; -use std::io; - -pub mod arp; -pub mod ethernet; - -const MAC: [u8; 6] = [0xf, 0xf, 0xf, 0xf, 0xe, 0x9]; -pub fn read_tap(buf: &mut [u8], read_fn: R, write_fn: W) -> io::Result -where - W: Fn(&[u8]) -> io::Result, - R: Fn(&mut [u8]) -> io::Result, -{ - let mut eth_buf = [0; 65536]; - loop { - let len = read_fn(&mut eth_buf)?; - if len == 0 { - return Ok(len); - } - //处理arp包 - let mut ether = ethernet::packet::EthernetPacket::new(&mut eth_buf[..len])?; - match ether.protocol() { - Protocol::Ipv4 => { - let len = ether.payload().len(); - if len > buf.len() { - return Err(io::Error::new(io::ErrorKind::Other, "short")); - } - buf[..len].copy_from_slice(ether.payload()); - return Ok(len); - } - Protocol::Arp => { - let mut arp_packet = arp::packet::ArpPacket::unchecked(ether.payload_mut()); - let sender_h: [u8; 6] = arp_packet.sender_hardware_addr().try_into().unwrap(); - let sender_p: [u8; 4] = arp_packet.sender_protocol_addr().try_into().unwrap(); - let target_p: [u8; 4] = arp_packet.target_protocol_addr().try_into().unwrap(); - if target_p == [0, 0, 0, 0] || sender_p == [0, 0, 0, 0] || target_p == sender_p { - continue; - } - if arp_packet.op_code() == 1 { - //回复一个默认的MAC - arp_packet.set_op_code(2); - arp_packet.set_target_hardware_addr(&sender_h); - arp_packet.set_target_protocol_addr(&sender_p); - arp_packet.set_sender_protocol_addr(&target_p); - arp_packet.set_sender_hardware_addr(&MAC); - ether.set_destination(&sender_h); - ether.set_source(&MAC); - write_fn(ether.buffer)?; - } - } - _ => { - //忽略这些数据 - } - } - } -} -pub fn write_tap(buf: &[u8], write_fn: W, mac: &[u8; 6]) -> io::Result -where - W: Fn(&[u8]) -> io::Result, -{ - // 封装二层数据 - let mut ether = ethernet::packet::EthernetPacket::unchecked(vec![0; 14 + buf.len()]); - ether.set_source(&MAC); - ether.set_destination(mac); - ether.set_protocol(Protocol::Ipv4); - ether.payload_mut().copy_from_slice(buf); - write_fn(ðer.buffer) -} diff --git a/vnt/tun/src/unix/fd.rs b/vnt/tun/src/unix/fd.rs deleted file mode 100644 index 7c2f973..0000000 --- a/vnt/tun/src/unix/fd.rs +++ /dev/null @@ -1,68 +0,0 @@ -use libc::{fcntl, F_GETFL, F_SETFL, O_NONBLOCK}; -use std::io; -use std::os::fd::{AsRawFd, IntoRawFd, RawFd}; - -pub struct Fd(pub RawFd); - -impl Fd { - pub fn new(value: RawFd) -> io::Result { - if value < 0 { - return Err(io::Error::from(io::ErrorKind::InvalidInput)); - } - Ok(Fd(value)) - } - pub fn set_nonblock(&self) -> io::Result<()> { - match unsafe { fcntl(self.0, F_SETFL, fcntl(self.0, F_GETFL) | O_NONBLOCK) } { - 0 => Ok(()), - _ => Err(io::Error::last_os_error()), - } - } -} - -impl Fd { - pub fn read(&self, buf: &mut [u8]) -> io::Result { - unsafe { - let amount = libc::read(self.0, buf.as_mut_ptr() as *mut _, buf.len()); - - if amount < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(amount as usize) - } - } - pub fn write(&self, buf: &[u8]) -> io::Result { - unsafe { - let amount = libc::write(self.0, buf.as_ptr() as *const _, buf.len()); - - if amount < 0 { - return Err(io::Error::last_os_error()); - } - - Ok(amount as usize) - } - } -} - -impl AsRawFd for Fd { - fn as_raw_fd(&self) -> RawFd { - self.0 - } -} - -impl IntoRawFd for Fd { - fn into_raw_fd(mut self) -> RawFd { - let fd = self.0; - self.0 = -1; - fd - } -} - -#[cfg(not(target_os = "android"))] -impl Drop for Fd { - fn drop(&mut self) { - unsafe { - libc::close(self.0); - } - } -} diff --git a/vnt/tun/src/unix/mod.rs b/vnt/tun/src/unix/mod.rs deleted file mode 100644 index 9d99dda..0000000 --- a/vnt/tun/src/unix/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -mod fd; - -pub use fd::Fd; -#[cfg(any(target_os = "macos", target_os = "linux"))] -use std::process::Output; -#[cfg(any(target_os = "macos", target_os = "linux"))] -mod sockaddr; -#[cfg(any(target_os = "macos", target_os = "linux"))] -pub use sockaddr::SockAddr; - -#[cfg(any(target_os = "macos", target_os = "linux"))] -pub fn exe_cmd(cmd: &str) -> std::io::Result { - use std::io; - use std::process::Command; - println!("exe cmd: {}", cmd); - let out = Command::new("sh") - .arg("-c") - .arg(cmd) - .output() - .expect("sh exec error!"); - if !out.status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("cmd={},out={:?}", cmd, out), - )); - } - Ok(out) -} diff --git a/vnt/tun/src/unix/sockaddr.rs b/vnt/tun/src/unix/sockaddr.rs deleted file mode 100644 index df67f25..0000000 --- a/vnt/tun/src/unix/sockaddr.rs +++ /dev/null @@ -1,67 +0,0 @@ -use libc::{in_addr, sockaddr, sockaddr_in}; -use std::{io, mem, net::Ipv4Addr, ptr}; - -use io::Result; - -/// A wrapper for `sockaddr_in`. -#[derive(Copy, Clone)] -pub struct SockAddr(sockaddr_in); - -impl SockAddr { - /// Create a new `SockAddr` from a generic `sockaddr`. - pub fn new(value: &sockaddr) -> Result { - if value.sa_family != libc::AF_INET as libc::sa_family_t { - return Err(io::Error::new(io::ErrorKind::Other, "invalid address")); - } - - unsafe { Self::unchecked(value) } - } - - /// # Safety - /// Create a new `SockAddr` and not check the source. - pub unsafe fn unchecked(value: &sockaddr) -> Result { - Ok(SockAddr(ptr::read(value as *const _ as *const _))) - } - - /// # Safety - /// Get a generic pointer to the `SockAddr`. - pub unsafe fn as_ptr(&self) -> *const sockaddr { - &self.0 as *const _ as *const sockaddr - } -} - -impl From for SockAddr { - fn from(ip: Ipv4Addr) -> SockAddr { - let octets = ip.octets(); - let mut addr = unsafe { mem::zeroed::() }; - - addr.sin_family = libc::AF_INET as libc::sa_family_t; - addr.sin_port = 0; - addr.sin_addr = in_addr { - s_addr: u32::from_ne_bytes(octets), - }; - - SockAddr(addr) - } -} - -impl From for Ipv4Addr { - fn from(addr: SockAddr) -> Ipv4Addr { - let ip = addr.0.sin_addr.s_addr; - let [a, b, c, d] = ip.to_ne_bytes(); - - Ipv4Addr::new(a, b, c, d) - } -} - -impl From for sockaddr { - fn from(addr: SockAddr) -> sockaddr { - unsafe { mem::transmute(addr.0) } - } -} - -impl From for sockaddr_in { - fn from(addr: SockAddr) -> sockaddr_in { - addr.0 - } -} diff --git a/vnt/tun/src/windows/check.rs b/vnt/tun/src/windows/check.rs deleted file mode 100644 index 2e34779..0000000 --- a/vnt/tun/src/windows/check.rs +++ /dev/null @@ -1,167 +0,0 @@ -use libloading::Library; -use std::ffi::{c_char, CStr, CString}; -use std::fs::File; -use std::io::{self, Read, Seek}; -use std::path::PathBuf; -use winapi::shared::minwindef::HINSTANCE; -use winapi::um::libloaderapi::{GetModuleFileNameA, GetModuleHandleA}; - -#[repr(C)] -#[derive(Debug)] -struct DosHeader { - e_magic: u16, - e_cblp: u16, - e_cp: u16, - e_crlc: u16, - e_cparhdr: u16, - e_minalloc: u16, - e_maxalloc: u16, - e_ss: u16, - e_sp: u16, - e_csum: u16, - e_ip: u16, - e_cs: u16, - e_lfarlc: u16, - e_ovno: u16, - e_res: [u16; 4], - e_oemid: u16, - e_oeminfo: u16, - e_res2: [u16; 10], - e_lfanew: i32, -} - -#[repr(C)] -#[derive(Debug)] -struct FileHeader { - machine: u16, - number_of_sections: u16, - time_date_stamp: u32, - pointer_to_symbol_table: u32, - number_of_symbols: u32, - size_of_optional_header: u16, - characteristics: u16, -} - -const IMAGE_FILE_MACHINE_I386: u16 = 0x014C; -const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664; -const IMAGE_FILE_MACHINE_ARM: u16 = 0x01C4; -const IMAGE_FILE_MACHINE_ARM64: u16 = 0xAA64; - -fn get_dll_path(dll_name: &str) -> Result { - unsafe { - // 使用libloading加载DLL - - // 转换DLL名称为C字符串 - let dll_name_c = - CString::new(dll_name).map_err(|e| format!("Failed to convert to CString: {}", e))?; - - // 获取DLL的模块句柄 - let h_instance: HINSTANCE = GetModuleHandleA(dll_name_c.as_ptr() as *const c_char); - - if h_instance.is_null() { - return Err("Failed to get module handle".to_string()); - } - - // 获取DLL文件路径 - let mut buffer: [c_char; 260] = [0; 260]; - let length = GetModuleFileNameA(h_instance, buffer.as_mut_ptr(), buffer.len() as u32); - - if length == 0 { - return Err("Failed to get module file name".to_string()); - } - - let path = CStr::from_ptr(buffer.as_ptr()); - let path_str = path - .to_str() - .map_err(|e| format!("Failed to convert to &str: {}", e))?; - Ok(PathBuf::from(path_str)) - } -} - -pub fn check_win_tun_dll() -> io::Result<()> { - let _lib = unsafe { - Library::new("wintun.dll").map_err(|_| { - io::Error::new( - io::ErrorKind::NotFound, - "wintun.dll not found,Please download https://www.wintun.net", - ) - }) - }; - match get_dll_path("wintun.dll") { - Ok(path) => match_platform(path), - Err(e) => { - // 能加载说明存在wintun,这里获取不到路径是代码的问题 - log::info!("{:?}", e); - Ok(()) - } - } -} - -fn match_platform(path: PathBuf) -> io::Result<()> { - let current_arch = if cfg!(target_arch = "x86") { - "x86" - } else if cfg!(target_arch = "x86_64") { - "AMD64" - } else if cfg!(target_arch = "arm") { - "ARM" - } else if cfg!(target_arch = "aarch64") { - "ARM64" - } else { - return Ok(()); - }; - - let mut file = File::open(&path)?; - - // 读取 DOS 头部 - let mut dos_header = [0u8; std::mem::size_of::()]; - file.read_exact(&mut dos_header)?; - let dos_header: DosHeader = unsafe { std::ptr::read(dos_header.as_ptr() as *const _) }; - - if dos_header.e_magic != 0x5A4D { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Not a valid PE file {:?}", path), - )); - } - - // 跳转到 PE 头部 - file.seek(io::SeekFrom::Start(dos_header.e_lfanew as u64))?; - - // 读取 PE 头部 - let mut pe_signature = [0u8; 4]; - file.read_exact(&mut pe_signature)?; - if &pe_signature != b"PE\0\0" { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Not a valid PE file {:?}", path), - )); - } - - // 读取文件头部 - let mut file_header = [0u8; std::mem::size_of::()]; - file.read_exact(&mut file_header)?; - let file_header: FileHeader = unsafe { std::ptr::read(file_header.as_ptr() as *const _) }; - let dll_arch = match file_header.machine { - IMAGE_FILE_MACHINE_I386 => "x86", - IMAGE_FILE_MACHINE_AMD64 => "AMD64", - IMAGE_FILE_MACHINE_ARM => "ARM", - IMAGE_FILE_MACHINE_ARM64 => "ARM64", - _ => { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Unknown machine type: {}", file_header.machine), - )) - } - }; - - if dll_arch != current_arch { - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "wintun.dll architecture ({}) does not match the current platform architecture ({}).", - dll_arch, current_arch - ), - )); - } - Ok(()) -} diff --git a/vnt/tun/src/windows/device.rs b/vnt/tun/src/windows/device.rs deleted file mode 100644 index d0f81e8..0000000 --- a/vnt/tun/src/windows/device.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::device::IFace; -use crate::windows::{tap, tun}; -use std::io; -use std::net::Ipv4Addr; - -pub enum Device { - Tap(tap::Device), - Tun(tun::Device), -} - -impl Device { - pub fn new(name: String, tap: bool) -> io::Result { - if tap { - Ok(Device::Tap(tap::Device::new(name)?)) - } else { - Ok(Device::Tun(tun::Device::new(name)?)) - } - } - pub fn check_tun_dll() -> io::Result<()> { - crate::windows::check::check_win_tun_dll() - } -} - -impl IFace for Device { - fn version(&self) -> io::Result { - match self { - Device::Tap(dev) => dev.version(), - Device::Tun(dev) => dev.version(), - } - } - - fn name(&self) -> io::Result { - match self { - Device::Tap(dev) => dev.name(), - Device::Tun(dev) => dev.name(), - } - } - - fn shutdown(&self) -> io::Result<()> { - match self { - Device::Tap(dev) => dev.shutdown(), - Device::Tun(dev) => dev.shutdown(), - } - } - - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> { - match self { - Device::Tap(dev) => dev.set_ip(address, mask), - Device::Tun(dev) => dev.set_ip(address, mask), - } - } - - fn mtu(&self) -> io::Result { - match self { - Device::Tap(dev) => dev.mtu(), - Device::Tun(dev) => dev.mtu(), - } - } - - fn set_mtu(&self, value: u32) -> io::Result<()> { - match self { - Device::Tap(dev) => dev.set_mtu(value), - Device::Tun(dev) => dev.set_mtu(value), - } - } - - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, metric: u16) -> io::Result<()> { - match self { - Device::Tap(dev) => dev.add_route(dest, netmask, metric), - Device::Tun(dev) => dev.add_route(dest, netmask, metric), - } - } - - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - match self { - Device::Tap(dev) => dev.delete_route(dest, netmask), - Device::Tun(dev) => dev.delete_route(dest, netmask), - } - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - match self { - Device::Tap(dev) => dev.read(buf), - Device::Tun(dev) => dev.read(buf), - } - } - - fn write(&self, buf: &[u8]) -> io::Result { - match self { - Device::Tap(dev) => dev.write(buf), - Device::Tun(dev) => dev.write(buf), - } - } -} diff --git a/vnt/tun/src/windows/ffi.rs b/vnt/tun/src/windows/ffi.rs deleted file mode 100644 index 466f6cc..0000000 --- a/vnt/tun/src/windows/ffi.rs +++ /dev/null @@ -1,502 +0,0 @@ -// Many things will be used in the future -#![allow(unused)] - -//! Module holding safe wrappers over winapi functions - -use winapi::shared::basetsd::*; -use winapi::shared::guiddef::GUID; -use winapi::shared::ifdef::*; -use winapi::shared::minwindef::*; -use winapi::shared::netioapi::*; -use winapi::shared::winerror::*; - -use winapi::um::combaseapi::*; -use winapi::um::errhandlingapi::*; -use winapi::um::fileapi::*; -use winapi::um::handleapi::*; -use winapi::um::ioapiset::*; -use winapi::um::setupapi::*; -use winapi::um::synchapi::*; -use winapi::um::winioctl::*; -use winapi::um::winnt::*; -use winapi::um::winreg::*; - -use std::error::Error; -use std::{io, mem, ptr}; -use winapi::um::minwinbase::OVERLAPPED_u; - -#[allow(non_camel_case_types)] -#[allow(non_snake_case)] -#[repr(C)] -#[derive(Clone, Copy)] -/// Custom type to handle variable size SP_DRVINFO_DETAIL_DATA_W -pub struct SP_DRVINFO_DETAIL_DATA_W2 { - pub cbSize: DWORD, - pub InfDate: FILETIME, - pub CompatIDsOffset: DWORD, - pub CompatIDsLength: DWORD, - pub Reserved: ULONG_PTR, - pub SectionName: [WCHAR; 256], - pub InfFileName: [WCHAR; 260], - pub DrvDescription: [WCHAR; 256], - pub HardwareID: [WCHAR; 512], -} - -pub fn string_from_guid(guid: &GUID) -> io::Result> { - // GUID_STRING_CHARACTERS + 1 - let mut string = vec![0; 39]; - - match unsafe { StringFromGUID2(guid, string.as_mut_ptr(), string.len() as _) } { - 0 => Err(io::Error::new(io::ErrorKind::Other, "Insufficent buffer")), - _ => Ok(string), - } -} - -pub fn alias_to_luid(alias: &[WCHAR]) -> io::Result { - let mut luid = unsafe { mem::zeroed() }; - - match unsafe { ConvertInterfaceAliasToLuid(alias.as_ptr(), &mut luid) } { - 0 => Ok(luid), - err => Err(io::Error::from_raw_os_error(err as _)), - } -} - -pub fn luid_to_index(luid: &NET_LUID) -> io::Result { - let mut index = 0; - - match unsafe { ConvertInterfaceLuidToIndex(luid, &mut index) } { - 0 => Ok(index), - err => Err(io::Error::from_raw_os_error(err as _)), - } -} - -pub fn luid_to_guid(luid: &NET_LUID) -> io::Result { - let mut guid = unsafe { mem::zeroed() }; - - match unsafe { ConvertInterfaceLuidToGuid(luid, &mut guid) } { - 0 => Ok(guid), - err => Err(io::Error::from_raw_os_error(err as _)), - } -} - -pub fn luid_to_alias(luid: &NET_LUID) -> io::Result> { - // IF_MAX_STRING_SIZE + 1 - let mut alias = vec![0; 257]; - - match unsafe { ConvertInterfaceLuidToAlias(luid, alias.as_mut_ptr(), alias.len()) } { - 0 => Ok(alias), - err => Err(io::Error::from_raw_os_error(err as _)), - } -} - -pub fn close_handle(handle: HANDLE) -> io::Result<()> { - match unsafe { CloseHandle(handle) } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn create_file( - file_name: &[WCHAR], - desired_access: DWORD, - share_mode: DWORD, - creation_disposition: DWORD, - flags_and_attributes: DWORD, -) -> io::Result { - match unsafe { - CreateFileW( - file_name.as_ptr(), - desired_access, - share_mode, - ptr::null_mut(), - creation_disposition, - flags_and_attributes, - ptr::null_mut(), - ) - } { - INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()), - handle => Ok(handle), - } -} - -pub fn read_file(handle: HANDLE, buffer: &mut [u8]) -> io::Result { - let mut ret = 0; - //https://www.cnblogs.com/linyilong3/archive/2012/05/03/2480451.html - unsafe { - let mut ip_overlapped = winapi::um::minwinbase::OVERLAPPED { - Internal: 0, - InternalHigh: 0, - u: Default::default(), - hEvent: ptr::null_mut(), - }; - if 0 == ReadFile( - handle, - buffer.as_mut_ptr() as _, - buffer.len() as _, - &mut ret, - &mut ip_overlapped, - ) { - let e = io::Error::last_os_error(); - if e.raw_os_error().unwrap_or(0) == ERROR_IO_PENDING as _ { - if 0 == GetOverlappedResult(handle, &mut ip_overlapped, &mut ret, 1) { - return Err(e); - } - } else { - return Err(e); - } - } - Ok(ret) - } -} - -pub fn write_file(handle: HANDLE, buffer: &[u8]) -> io::Result { - let mut ret = 0; - let mut ip_overlapped = winapi::um::minwinbase::OVERLAPPED { - Internal: 0, - InternalHigh: 0, - u: Default::default(), - hEvent: ptr::null_mut(), - }; - unsafe { - if 0 == WriteFile( - handle, - buffer.as_ptr() as _, - buffer.len() as _, - &mut ret, - &mut ip_overlapped, - ) { - let e = io::Error::last_os_error(); - if e.raw_os_error().unwrap_or(0) == ERROR_IO_PENDING as _ { - if 0 == GetOverlappedResult(handle, &mut ip_overlapped, &mut ret, 1) { - return Err(e); - } - } else { - return Err(e); - } - } - Ok(ret) - } -} - -pub fn create_device_info_list(guid: &GUID) -> io::Result { - match unsafe { SetupDiCreateDeviceInfoList(guid, ptr::null_mut()) } { - INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()), - devinfo => Ok(devinfo), - } -} - -pub fn get_class_devs(guid: &GUID, flags: DWORD) -> io::Result { - match unsafe { SetupDiGetClassDevsW(guid, ptr::null(), ptr::null_mut(), flags) } { - INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()), - devinfo => Ok(devinfo), - } -} - -pub fn destroy_device_info_list(devinfo: HDEVINFO) -> io::Result<()> { - match unsafe { SetupDiDestroyDeviceInfoList(devinfo) } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn class_name_from_guid(guid: &GUID) -> io::Result> { - let mut class_name = vec![0; 32]; - - match unsafe { - SetupDiClassNameFromGuidW( - guid, - class_name.as_mut_ptr(), - class_name.len() as _, - ptr::null_mut(), - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(class_name), - } -} - -pub fn create_device_info( - devinfo: HDEVINFO, - device_name: &[WCHAR], - guid: &GUID, - device_description: &[WCHAR], - creation_flags: DWORD, -) -> io::Result { - let mut devinfo_data: SP_DEVINFO_DATA = unsafe { mem::zeroed() }; - devinfo_data.cbSize = mem::size_of_val(&devinfo_data) as _; - - match unsafe { - SetupDiCreateDeviceInfoW( - devinfo, - device_name.as_ptr(), - guid, - device_description.as_ptr(), - ptr::null_mut(), - creation_flags, - &mut devinfo_data, - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(devinfo_data), - } -} - -pub fn set_selected_device(devinfo: HDEVINFO, devinfo_data: &SP_DEVINFO_DATA) -> io::Result<()> { - match unsafe { SetupDiSetSelectedDevice(devinfo, devinfo_data as *const _ as _) } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn set_device_registry_property( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - property: DWORD, - value: &[WCHAR], -) -> io::Result<()> { - match unsafe { - SetupDiSetDeviceRegistryPropertyW( - devinfo, - devinfo_data as *const _ as _, - property, - value.as_ptr() as _, - (value.len() * 2) as _, - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn get_device_registry_property( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - property: DWORD, -) -> io::Result> { - let mut value = vec![0; 32]; - - match unsafe { - SetupDiGetDeviceRegistryPropertyW( - devinfo, - devinfo_data as *const _ as _, - property, - ptr::null_mut(), - value.as_mut_ptr() as _, - (value.len() * 2) as _, - ptr::null_mut(), - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(value), - } -} - -pub fn build_driver_info_list( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - driver_type: DWORD, -) -> io::Result<()> { - match unsafe { SetupDiBuildDriverInfoList(devinfo, devinfo_data as *const _ as _, driver_type) } - { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn destroy_driver_info_list( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - driver_type: DWORD, -) -> io::Result<()> { - match unsafe { - SetupDiDestroyDriverInfoList(devinfo, devinfo_data as *const _ as _, driver_type) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn get_driver_info_detail( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - drvinfo_data: &SP_DRVINFO_DATA_W, -) -> io::Result { - let mut drvinfo_detail: SP_DRVINFO_DETAIL_DATA_W2 = unsafe { mem::zeroed() }; - drvinfo_detail.cbSize = mem::size_of::() as _; - - match unsafe { - SetupDiGetDriverInfoDetailW( - devinfo, - devinfo_data as *const _ as _, - drvinfo_data as *const _ as _, - &mut drvinfo_detail as *mut _ as _, - mem::size_of_val(&drvinfo_detail) as _, - ptr::null_mut(), - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(drvinfo_detail), - } -} - -pub fn set_selected_driver( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - drvinfo_data: &SP_DRVINFO_DATA_W, -) -> io::Result<()> { - match unsafe { - SetupDiSetSelectedDriverW( - devinfo, - devinfo_data as *const _ as _, - drvinfo_data as *const _ as _, - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn set_class_install_params( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - params: &impl Copy, -) -> io::Result<()> { - match unsafe { - SetupDiSetClassInstallParamsW( - devinfo, - devinfo_data as *const _ as _, - params as *const _ as _, - mem::size_of_val(params) as _, - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn call_class_installer( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - install_function: DI_FUNCTION, -) -> io::Result<()> { - match unsafe { - SetupDiCallClassInstaller(install_function, devinfo, devinfo_data as *const _ as _) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} - -pub fn open_dev_reg_key( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - scope: DWORD, - hw_profile: DWORD, - key_type: DWORD, - sam_desired: REGSAM, -) -> io::Result { - const INVALID_KEY_VALUE: HKEY = INVALID_HANDLE_VALUE as _; - - match unsafe { - SetupDiOpenDevRegKey( - devinfo, - devinfo_data as *const _ as _, - scope, - hw_profile, - key_type, - sam_desired, - ) - } { - INVALID_KEY_VALUE => Err(io::Error::last_os_error()), - key => Ok(key), - } -} - -pub fn notify_change_key_value( - key: HKEY, - watch_subtree: BOOL, - notify_filter: DWORD, - milliseconds: DWORD, -) -> io::Result<()> { - let event = match unsafe { CreateEventW(ptr::null_mut(), FALSE, FALSE, ptr::null()) } { - INVALID_HANDLE_VALUE => Err(io::Error::last_os_error()), - event => Ok(event), - }?; - - match unsafe { RegNotifyChangeKeyValue(key, watch_subtree, notify_filter, event, TRUE) } { - 0 => Ok(()), - err => Err(io::Error::from_raw_os_error(err)), - }?; - - match unsafe { WaitForSingleObject(event, milliseconds) } { - 0 => Ok(()), - 0x102 => Err(io::Error::new( - io::ErrorKind::TimedOut, - "Registry timed out", - )), - _ => Err(io::Error::last_os_error()), - } -} - -pub fn enum_driver_info( - devinfo: HDEVINFO, - devinfo_data: &SP_DEVINFO_DATA, - driver_type: DWORD, - member_index: DWORD, -) -> Option> { - let mut drvinfo_data: SP_DRVINFO_DATA_W = unsafe { mem::zeroed() }; - drvinfo_data.cbSize = mem::size_of_val(&drvinfo_data) as _; - - match unsafe { - SetupDiEnumDriverInfoW( - devinfo, - devinfo_data as *const _ as _, - driver_type, - member_index, - &mut drvinfo_data, - ) - } { - 0 if unsafe { GetLastError() == ERROR_NO_MORE_ITEMS } => None, - 0 => Some(Err(io::Error::last_os_error())), - _ => Some(Ok(drvinfo_data)), - } -} - -pub fn enum_device_info( - devinfo: HDEVINFO, - member_index: DWORD, -) -> Option> { - let mut devinfo_data: SP_DEVINFO_DATA = unsafe { mem::zeroed() }; - devinfo_data.cbSize = mem::size_of_val(&devinfo_data) as _; - - match unsafe { SetupDiEnumDeviceInfo(devinfo, member_index, &mut devinfo_data) } { - 0 if unsafe { GetLastError() == ERROR_NO_MORE_ITEMS } => None, - 0 => Some(Err(io::Error::last_os_error())), - _ => Some(Ok(devinfo_data)), - } -} - -pub fn device_io_control( - handle: HANDLE, - io_control_code: DWORD, - in_buffer: &impl Copy, - out_buffer: &mut impl Copy, -) -> io::Result<()> { - let mut junk = 0; - - match unsafe { - DeviceIoControl( - handle, - io_control_code, - in_buffer as *const _ as _, - mem::size_of_val(in_buffer) as _, - out_buffer as *mut _ as _, - mem::size_of_val(out_buffer) as _, - &mut junk, - ptr::null_mut(), - ) - } { - 0 => Err(io::Error::last_os_error()), - _ => Ok(()), - } -} diff --git a/vnt/tun/src/windows/mod.rs b/vnt/tun/src/windows/mod.rs deleted file mode 100644 index cc3a17a..0000000 --- a/vnt/tun/src/windows/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -use std::io; -use std::os::windows::process::CommandExt; -use winapi::shared::minwindef::DWORD; -use winapi::um::winbase::CREATE_NO_WINDOW; - -mod check; -mod device; -mod ffi; -mod netsh; -mod route; -mod tap; -mod tun; -pub use device::Device; - -/// Encode a string as a utf16 buffer -pub fn encode_utf16(string: &str) -> Vec { - use std::iter::once; - string.encode_utf16().chain(once(0)).collect() -} - -pub fn decode_utf16(string: &[u16]) -> String { - let end = string.iter().position(|b| *b == 0).unwrap_or(string.len()); - String::from_utf16_lossy(&string[..end]) -} - -pub const fn ctl_code(device_type: DWORD, function: DWORD, method: DWORD, access: DWORD) -> DWORD { - (device_type << 16) | (access << 14) | (function << 2) | method -} - -pub fn exe_cmd(cmd: &str) -> io::Result<()> { - println!("exe cmd: {}", cmd); - let out = std::process::Command::new("cmd") - .creation_flags(CREATE_NO_WINDOW) - .arg("/C") - .arg(&cmd) - .output()?; - if !out.status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("cmd={},out={:?}", cmd, String::from_utf8(out.stderr)), - )); - } - Ok(()) -} diff --git a/vnt/tun/src/windows/netsh.rs b/vnt/tun/src/windows/netsh.rs deleted file mode 100644 index d2e3962..0000000 --- a/vnt/tun/src/windows/netsh.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![allow(dead_code)] -use crate::windows::exe_cmd; -use std::io; -use std::net::Ipv4Addr; - -/// 设置网卡名称 -pub fn set_interface_name(old_name: &str, new_name: &str) -> io::Result<()> { - let cmd = format!( - " netsh interface set interface name={:?} newname={:?}", - old_name, new_name - ); - exe_cmd(&cmd) -} -/// 删除缓存 -pub fn delete_cache() -> io::Result<()> { - //清除缓存 - let cmd = "netsh interface ip delete destinationcache"; - exe_cmd(cmd) -} - -/// 设置网卡ip -pub fn set_interface_ip(index: u32, address: &Ipv4Addr, netmask: &Ipv4Addr) -> io::Result<()> { - let cmd = format!( - "netsh interface ip set address {} static {:?} {:?} ", - index, address, netmask, - ); - exe_cmd(&cmd) -} - -pub fn set_interface_mtu(index: u32, mtu: u32) -> io::Result<()> { - let cmd = format!( - "netsh interface ipv4 set subinterface {} mtu={} store=persistent", - index, mtu - ); - exe_cmd(&cmd) -} -pub fn set_interface_metric(index: u32, metric: u16) -> io::Result<()> { - let cmd = format!( - "netsh interface ip set interface {} metric={}", - index, metric - ); - exe_cmd(&cmd) -} -/// 禁用ipv6 -pub fn disabled_ipv6(index: u32) -> io::Result<()> { - let cmd = format!("netsh interface ipv6 set interface {} disabled", index); - exe_cmd(&cmd) -} diff --git a/vnt/tun/src/windows/route.rs b/vnt/tun/src/windows/route.rs deleted file mode 100644 index 11ebfed..0000000 --- a/vnt/tun/src/windows/route.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::io; -use std::net::Ipv4Addr; - -use crate::windows::exe_cmd; - -/// 添加路由 -pub fn add_route( - index: u32, - dest: Ipv4Addr, - netmask: Ipv4Addr, - gateway: Ipv4Addr, - metric: u16, -) -> io::Result<()> { - let cmd = format!( - "route add {:?} mask {:?} {:?} metric {} if {}", - dest, netmask, gateway, metric, index - ); - exe_cmd(&cmd) -} - -/// 删除路由 -pub fn delete_route( - index: u32, - dest: Ipv4Addr, - netmask: Ipv4Addr, - gateway: Ipv4Addr, -) -> io::Result<()> { - let cmd = format!( - "route delete {:?} mask {:?} {:?} if {}", - dest, netmask, gateway, index - ); - exe_cmd(&cmd) -} diff --git a/vnt/tun/src/windows/tap/mod.rs b/vnt/tun/src/windows/tap/mod.rs deleted file mode 100644 index 74c5c0a..0000000 --- a/vnt/tun/src/windows/tap/mod.rs +++ /dev/null @@ -1,185 +0,0 @@ -#![allow(dead_code)] -use std::io; -use std::net::Ipv4Addr; -use winapi::shared::ifdef::NET_LUID; -use winapi::shared::minwindef::DWORD; -use winapi::um::fileapi::OPEN_EXISTING; -use winapi::um::winbase::FILE_FLAG_OVERLAPPED; -use winapi::um::winioctl::{FILE_ANY_ACCESS, FILE_DEVICE_UNKNOWN, METHOD_BUFFERED}; -use winapi::um::winnt::{ - FILE_ATTRIBUTE_SYSTEM, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE, -}; - -use crate::device::IFace; -use crate::packet; -use crate::windows::{ctl_code, decode_utf16, encode_utf16, ffi, netsh, route}; - -/* Present in 8.1 */ -const TAP_WIN_IOCTL_GET_MAC: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_GET_VERSION: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 2, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_GET_MTU: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 3, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_GET_INFO: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 4, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 5, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_SET_MEDIA_STATUS: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 6, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_CONFIG_DHCP_MASQ: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 7, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_GET_LOG_LINE: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 8, METHOD_BUFFERED, FILE_ANY_ACCESS); -const TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 9, METHOD_BUFFERED, FILE_ANY_ACCESS); -/* Added in 8.2 */ -/* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */ -const TAP_WIN_IOCTL_CONFIG_TUN: DWORD = - ctl_code(FILE_DEVICE_UNKNOWN, 10, METHOD_BUFFERED, FILE_ANY_ACCESS); - -pub struct Device { - handle: HANDLE, - index: u32, - luid: NET_LUID, - mac: [u8; 6], -} - -unsafe impl Send for Device {} - -unsafe impl Sync for Device {} - -impl Device { - /// 打开设备,设置为TUN模式,激活网卡 - pub fn new(name: String) -> io::Result { - let luid = ffi::alias_to_luid(&encode_utf16(&name)).map_err(|e| { - io::Error::new(e.kind(), format!("alias_to_luid name={},err={:?}", name, e)) - })?; - let guid = ffi::luid_to_guid(&luid) - .and_then(|guid| ffi::string_from_guid(&guid)) - .map_err(|e| { - io::Error::new(e.kind(), format!("luid_to_guid name={},err={:?}", name, e)) - })?; - let path = format!(r"\\.\Global\{}.tap", decode_utf16(&guid)); - let handle = ffi::create_file( - &encode_utf16(&path), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - ) - .map_err(|e| io::Error::new(e.kind(), format!("tap name={},err={:?}", name, e)))?; - - // ep保存tun网卡的IP地址和掩码 - // let mut ep = [0;3]; - // ep[0] = Ipv4Addr::new(10,26,0,11).into(); - // ep[2] = Ipv4Addr::new(255,255,255,0).into();; - // ep[1] = ep[0] & ep[2]; - // //tun模式收不到ipv4包,原因未知 https://github.com/OpenVPN/tap-windows6/issues/111 - // ffi::device_io_control(handle, TAP_WIN_IOCTL_CONFIG_TUN, &ep, &mut ()).map_err( - // |e| { - // io::Error::new( - // e.kind(), - // format!("TAP_WIN_IOCTL_CONFIG_TUN name={},err={:?}", name_str, e), - // ) - // }, - // )?; - let mut mac = [0u8; 6]; - ffi::device_io_control(handle, TAP_WIN_IOCTL_GET_MAC, &(), &mut mac) - .map_err(|e| { - io::Error::new( - e.kind(), - format!("TAP_WIN_IOCTL_CONFIG_TUN name={},err={:?}", name, e), - ) - }) - .map_err(|e| io::Error::new(e.kind(), format!("TAP_WIN_IOCTL_GET_MAC,err={:?}", e)))?; - let index = ffi::luid_to_index(&luid).map(|index| index as u32)?; - // 设置网卡跃点 - if let Err(e) = netsh::set_interface_metric(index, 0) { - log::warn!("{:?}", e); - } - let device = Self { - handle, - index, - luid, - mac, - }; - device.enabled(true)?; - Ok(device) - } - fn write_tap(&self, buf: &[u8]) -> io::Result { - ffi::write_file(self.handle, buf).map(|res| res as _) - } - fn enabled(&self, value: bool) -> io::Result<()> { - let status: u32 = if value { 1 } else { 0 }; - ffi::device_io_control( - self.handle, - TAP_WIN_IOCTL_SET_MEDIA_STATUS, - &status, - &mut (), - ) - } -} - -impl IFace for Device { - fn version(&self) -> io::Result { - let mut version = [0u32; 3]; - ffi::device_io_control(self.handle, TAP_WIN_IOCTL_GET_VERSION, &(), &mut version)?; - Ok(format!("{}.{}.{}", version[0], version[1], version[2])) - } - fn name(&self) -> io::Result { - ffi::luid_to_alias(&self.luid).map(|name| decode_utf16(&name)) - } - - fn shutdown(&self) -> io::Result<()> { - self.enabled(false) - } - - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> { - netsh::set_interface_ip(self.index, &address, &mask) - } - - fn mtu(&self) -> io::Result { - let mut mtu = 0; - ffi::device_io_control(self.handle, TAP_WIN_IOCTL_GET_MTU, &(), &mut mtu).map(|_| mtu) - } - - fn set_mtu(&self, value: u32) -> io::Result<()> { - netsh::set_interface_mtu(self.index, value) - } - - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, metric: u16) -> io::Result<()> { - route::add_route(self.index, dest, netmask, Ipv4Addr::UNSPECIFIED, metric)?; - netsh::delete_cache() - } - - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - route::delete_route(self.index, dest, netmask, Ipv4Addr::UNSPECIFIED)?; - netsh::delete_cache() - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - packet::read_tap( - buf, - |eth_buf| ffi::read_file(self.handle, eth_buf).map(|res| res as usize), - |eth_buf| ffi::write_file(self.handle, eth_buf).map(|res| res as _), - ) - } - - fn write(&self, buf: &[u8]) -> io::Result { - // 封装二层数据 - packet::write_tap( - buf, - |eth_buf| ffi::write_file(self.handle, eth_buf).map(|res| res as _), - &self.mac, - ) - } -} - -impl Drop for Device { - fn drop(&mut self) { - if let Err(e) = ffi::close_handle(self.handle) { - log::warn!("close_handle={:?}", e) - } - } -} diff --git a/vnt/tun/src/windows/tun/mod.rs b/vnt/tun/src/windows/tun/mod.rs deleted file mode 100644 index 27438bd..0000000 --- a/vnt/tun/src/windows/tun/mod.rs +++ /dev/null @@ -1,363 +0,0 @@ -#![allow(dead_code)] -use libloading::Library; -use sha2::Digest; -use std::io; -use std::net::Ipv4Addr; -use winapi::um::winbase; -use winapi::um::{synchapi, winnt}; - -use crate::device::IFace; -use crate::windows::decode_utf16; -use crate::windows::{encode_utf16, ffi, netsh, route}; - -mod packet; -mod wintun_log; -mod wintun_raw; - -/// The maximum size of wintun's internal ring buffer (in bytes) -pub const MAX_RING_CAPACITY: u32 = 0x400_0000; - -/// The minimum size of wintun's internal ring buffer (in bytes) -pub const MIN_RING_CAPACITY: u32 = 0x2_0000; - -/// Maximum pool name length including zero terminator -pub const MAX_POOL: usize = 256; - -pub struct Device { - pub(crate) luid: u64, - pub(crate) index: u32, - /// The session handle given to us by WintunStartSession - pub(crate) session: wintun_raw::WINTUN_SESSION_HANDLE, - - /// Shared dll for required wintun driver functions - pub(crate) win_tun: wintun_raw::wintun, - - /// Windows event handle that is signaled by the wintun driver when data becomes available to - /// read - pub(crate) read_event: winnt::HANDLE, - - /// Windows event handle that is signaled when [`TunSession::shutdown`] is called force blocking - /// readers to exit - pub(crate) shutdown_event: winnt::HANDLE, - - /// The adapter that owns this session - pub(crate) adapter: wintun_raw::WINTUN_ADAPTER_HANDLE, -} - -unsafe impl Send for Device {} - -unsafe impl Sync for Device {} - -impl Device { - pub fn new(name: String) -> io::Result { - unsafe { - let library = match Library::new("wintun.dll") { - Ok(library) => library, - Err(e) => { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("wintun.dll not found {:?}", e), - )); - } - }; - let win_tun = match wintun_raw::wintun::from_library(library) { - Ok(win_tun) => win_tun, - Err(e) => { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("library error {:?} ", e), - )); - } - }; - let name_utf16 = encode_utf16(&name); - if name_utf16.len() > MAX_POOL { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("too long {}:{:?}", MAX_POOL, name), - )); - } - wintun_log::set_default_logger_if_unset(&win_tun); - if Self::delete_for_name(&win_tun, &name_utf16).is_ok() { - std::thread::sleep(std::time::Duration::from_millis(500)); - } - let guid_bytes: [u8; 16] = hash_guid(&name); - let guid = u128::from_ne_bytes(guid_bytes); - //SAFETY: guid is a unique integer so transmuting either all zeroes or the user's preferred - //guid to the winapi guid type is safe and will allow the windows kernel to see our GUID - - let guid_struct: wintun_raw::GUID = std::mem::transmute(guid); - let guid_ptr = &guid_struct as *const wintun_raw::GUID; - - //SAFETY: the function is loaded from the wintun dll properly, we are providing valid - //pointers, and all the strings are correct null terminated UTF-16. This safety rationale - //applies for all Wintun* functions below - let adapter = - win_tun.WintunCreateAdapter(name_utf16.as_ptr(), name_utf16.as_ptr(), guid_ptr); - if adapter.is_null() { - log::error!("adapter.is_null {:?}", io::Error::last_os_error()); - return Err(io::Error::new( - io::ErrorKind::Other, - "Failed to crate adapter", - )); - } - // 开启session - let session = win_tun.WintunStartSession(adapter, 4 * 1024 * 1024); - if session.is_null() { - log::error!("session.is_null {:?}", io::Error::last_os_error()); - return Err(io::Error::new( - io::ErrorKind::Other, - "WintunStartSession failed", - )); - } - //SAFETY: We follow the contract required by CreateEventA. See MSDN - //(the pointers are allowed to be null, and 0 is okay for the others) - let shutdown_event = - synchapi::CreateEventA(std::ptr::null_mut(), 0, 0, std::ptr::null_mut()); - let read_event = win_tun.WintunGetReadWaitEvent(session) as winnt::HANDLE; - let mut luid: wintun_raw::NET_LUID = std::mem::zeroed(); - win_tun.WintunGetAdapterLUID(adapter, &mut luid as *mut wintun_raw::NET_LUID); - let index = ffi::luid_to_index(&std::mem::transmute(luid)).map(|index| index as u32)?; - // 设置网卡跃点 - if let Err(e) = netsh::set_interface_metric(index, 0) { - log::warn!("{:?}", e); - } - Ok(Self { - luid: std::mem::transmute(luid), - index, - session, - win_tun, - read_event, - shutdown_event, - adapter, - }) - } - } - pub unsafe fn delete_for_name( - win_tun: &wintun_raw::wintun, - name_utf16: &Vec, - ) -> io::Result<()> { - let adapter = win_tun.WintunOpenAdapter(name_utf16.as_ptr()); - if adapter.is_null() { - log::error!( - "delete_for_name adapter.is_null {:?}", - io::Error::last_os_error() - ); - return Err(io::Error::new( - io::ErrorKind::Other, - "Failed to open adapter", - )); - } - win_tun.WintunCloseAdapter(adapter); - win_tun.WintunDeleteDriver(); - Ok(()) - } -} -fn hash_guid(input: &str) -> [u8; 16] { - let mut hasher = sha2::Sha256::new(); - hasher.update(input.as_bytes()); - hasher.update(b"VNT"); - hasher.update(input.as_bytes()); - hasher.update(b"2024"); - let hash: [u8; 32] = hasher.finalize().into(); - hash[..16].try_into().unwrap() -} -impl IFace for Device { - fn version(&self) -> io::Result { - let version = unsafe { self.win_tun.WintunGetRunningDriverVersion() }; - if version == 0 { - return Err(io::Error::new( - io::ErrorKind::Other, - "WintunGetRunningDriverVersion", - )); - } else { - Ok(format!("{}.{}", (version >> 16) & 0xFFFF, version & 0xFFFF)) - } - } - fn name(&self) -> io::Result { - let luid = self.luid; - ffi::luid_to_alias(&unsafe { std::mem::transmute(luid) }).map(|name| decode_utf16(&name)) - } - - fn shutdown(&self) -> io::Result<()> { - unsafe { - if winapi::shared::minwindef::TRUE == synchapi::SetEvent(self.shutdown_event) { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - } - - fn set_ip(&self, address: Ipv4Addr, mask: Ipv4Addr) -> io::Result<()> { - netsh::set_interface_ip(self.index, &address, &mask) - } - - fn mtu(&self) -> io::Result { - Err(io::Error::from(io::ErrorKind::Unsupported)) - } - - fn set_mtu(&self, value: u32) -> io::Result<()> { - netsh::set_interface_mtu(self.index, value) - } - - fn add_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr, metric: u16) -> io::Result<()> { - route::add_route(self.index, dest, netmask, Ipv4Addr::UNSPECIFIED, metric)?; - netsh::delete_cache() - } - - fn delete_route(&self, dest: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> { - route::delete_route(self.index, dest, netmask, Ipv4Addr::UNSPECIFIED)?; - netsh::delete_cache() - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - let packet = self.receive_blocking()?; - let packet = packet.bytes(); - let len = packet.len(); - if len > buf.len() { - return Err(io::Error::new(io::ErrorKind::InvalidData, "data too long")); - } - buf[..len].copy_from_slice(packet); - Ok(len) - } - - fn write(&self, buf: &[u8]) -> io::Result { - let mut packet = self.allocate_send_packet(buf.len() as u16)?; - packet.bytes_mut().copy_from_slice(buf); - self.send_packet(packet); - Ok(buf.len()) - } -} - -impl Device { - pub fn try_receive(&self) -> io::Result> { - let mut size = 0u32; - - let bytes_ptr = unsafe { - self.win_tun - .WintunReceivePacket(self.session, &mut size as *mut u32) - }; - - debug_assert!(size <= u16::MAX as u32); - if bytes_ptr.is_null() { - //Wintun returns ERROR_NO_MORE_ITEMS instead of blocking if packets are not available - let last_error = unsafe { winapi::um::errhandlingapi::GetLastError() }; - if last_error == winapi::shared::winerror::ERROR_NO_MORE_ITEMS { - Ok(None) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!("try_receive failed {:?}", io::Error::last_os_error()), - )) - } - } else { - Ok(Some(packet::TunPacket { - kind: packet::Kind::ReceivePacket, - size: size as usize, - //SAFETY: ptr is non null, aligned for u8, and readable for up to size bytes (which - //must be less than isize::MAX because bytes is a u16 - bytes_ptr, - tun_device: Some(&self), - })) - } - } - pub fn receive_blocking(&self) -> io::Result { - loop { - //Try 16 times to receive without blocking so we don't have to issue a syscall to wait - //for the event if packets are being received at a rapid rate - for i in 0..20 { - match self.try_receive() { - Ok(data) => match data { - None => { - continue; - } - Some(packet) => { - return Ok(packet); - } - }, - Err(e) => { - if i > 10 { - // 某些系统存在错误退出的情况(原因不明),这里尝试忽略部分错误 - return Err(e); - } - } - } - } - //Wait on both the read handle and the shutdown handle so that we stop when requested - let handles = [self.read_event, self.shutdown_event]; - let result = unsafe { - //SAFETY: We abide by the requirements of WaitForMultipleObjects, handles is a - //pointer to valid, aligned, stack memory - synchapi::WaitForMultipleObjects( - 2, - &handles as *const winnt::HANDLE, - 0, - winbase::INFINITE, - ) - }; - match result { - winbase::WAIT_FAILED => { - return Err(io::Error::new(io::ErrorKind::Other, "WAIT_FAILED")); - } - _ => { - if result == winbase::WAIT_OBJECT_0 { - //We have data! - continue; - } else { - //Shutdown event triggered - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Shutdown event triggered {}", io::Error::last_os_error()), - )); - } - } - } - } - } - pub fn allocate_send_packet(&self, size: u16) -> io::Result { - let bytes_ptr = unsafe { - self.win_tun - .WintunAllocateSendPacket(self.session, size as u32) - }; - if bytes_ptr.is_null() { - Err(io::Error::new( - io::ErrorKind::Other, - "allocate_send_packet failed", - )) - } else { - Ok(packet::TunPacket { - kind: packet::Kind::SendPacketPending, - size: size as usize, - //SAFETY: ptr is non null, aligned for u8, and readable for up to size bytes (which - //must be less than isize::MAX because bytes is a u16 - bytes_ptr, - tun_device: None, - }) - } - } - pub fn send_packet(&self, mut packet: packet::TunPacket) { - assert!(matches!(packet.kind, packet::Kind::SendPacketPending)); - - unsafe { - self.win_tun - .WintunSendPacket(self.session, packet.bytes_ptr) - }; - //Mark the packet at sent - packet.kind = packet::Kind::SendPacketSent; - } -} - -impl Drop for Device { - fn drop(&mut self) { - unsafe { - if let Err(e) = ffi::close_handle(self.shutdown_event) { - log::warn!("close shutdown_event={:?}", e) - } - self.win_tun.WintunEndSession(self.session); - self.win_tun.WintunCloseAdapter(self.adapter); - if winapi::shared::minwindef::FALSE == self.win_tun.WintunDeleteDriver() { - log::warn!("WintunDeleteDriver failed {:?}", io::Error::last_os_error()) - } - } - } -} diff --git a/vnt/tun/src/windows/tun/packet.rs b/vnt/tun/src/windows/tun/packet.rs deleted file mode 100644 index f1b003b..0000000 --- a/vnt/tun/src/windows/tun/packet.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::windows::tun::Device; - -pub(crate) enum Kind { - SendPacketPending, - //Send packet type, but not sent yet - SendPacketSent, - //Send packet type - sent - ReceivePacket, -} - -/// Represents a wintun packet -pub struct TunPacket<'a> { - pub(crate) kind: Kind, - pub(crate) size: usize, - pub(crate) bytes_ptr: *const u8, - - //Share ownership of session to prevent the session from being dropped before packets that - //belong to it - pub(crate) tun_device: Option<&'a Device>, -} - -impl<'a> TunPacket<'a> { - /// Returns the bytes this packet holds as &mut. - /// The lifetime of the bytes is tied to the lifetime of this packet. - pub fn bytes_mut(&mut self) -> &mut [u8] { - unsafe { std::slice::from_raw_parts_mut(self.bytes_ptr as *mut u8, self.size) } - } - - /// Returns an immutable reference to the bytes this packet holds. - /// The lifetime of the bytes is tied to the lifetime of this packet. - pub fn bytes(&self) -> &[u8] { - unsafe { std::slice::from_raw_parts(self.bytes_ptr, self.size) } - } -} - -impl<'a> Drop for TunPacket<'a> { - fn drop(&mut self) { - match self.kind { - Kind::ReceivePacket => { - unsafe { - //SAFETY: - // - // 1. We share ownership of the session therefore it hasn't been dropped yet - // 2. Bytes is valid because each packet holds exclusive access to a region of the - // ring buffer that the wintun session owns. We return that region of - // memory back to wintun here - let tun_device = self.tun_device.unwrap(); - tun_device - .win_tun - .WintunReleaseReceivePacket(tun_device.session, self.bytes_ptr) - }; - } - Kind::SendPacketPending => { - //If someone allocates a packet with session.allocate_send_packet() and then it is - //dropped without being sent, this will hold up the send queue because wintun expects - //that every allocated packet is sent - panic!("Packet was never sent!"); - } - Kind::SendPacketSent => { - //Nop - } - } - } -} diff --git a/vnt/tun/src/windows/tun/wintun_log.rs b/vnt/tun/src/windows/tun/wintun_log.rs deleted file mode 100644 index 4472cf2..0000000 --- a/vnt/tun/src/windows/tun/wintun_log.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![allow(dead_code)] -use log::*; - -use crate::windows::tun::wintun_raw; -use std::sync::atomic::{AtomicBool, Ordering}; -use widestring::U16CStr; - -/// Sets the logger wintun will use when logging. Maps to the WintunSetLogger C function -pub fn set_logger(win_tun: &wintun_raw::wintun, f: wintun_raw::WINTUN_LOGGER_CALLBACK) { - unsafe { win_tun.WintunSetLogger(f) }; -} - -pub fn reset_logger(win_tun: &wintun_raw::wintun) { - set_logger(win_tun, None); -} - -static SET_LOGGER: AtomicBool = AtomicBool::new(false); - -/// The logger that is active by default. Logs messages to the log crate -/// -/// # Safety -/// `message` must be a valid pointer that points to an aligned null terminated UTF-16 string -pub unsafe extern "C" fn default_logger( - level: wintun_raw::WINTUN_LOGGER_LEVEL, - _timestamp: wintun_raw::DWORD64, - message: *const wintun_raw::WCHAR, -) { - //Cant wait for RFC 2585 - #[allow(unused_unsafe)] - //Wintun will always give us a valid UTF16 null termineted string - let msg = unsafe { U16CStr::from_ptr_str(message) }; - let utf8_msg = msg.to_string_lossy(); - match level { - wintun_raw::WINTUN_LOGGER_LEVEL_WINTUN_LOG_INFO => info!("WinTun: {}", utf8_msg), - wintun_raw::WINTUN_LOGGER_LEVEL_WINTUN_LOG_WARN => warn!("WinTun: {}", utf8_msg), - wintun_raw::WINTUN_LOGGER_LEVEL_WINTUN_LOG_ERR => error!("WinTun: {}", utf8_msg), - _ => error!("WinTun: {} (with invalid log level {})", utf8_msg, level), - } -} - -pub(crate) fn set_default_logger_if_unset(win_tun: &wintun_raw::wintun) { - if SET_LOGGER - .compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed) - .is_ok() - { - set_logger(win_tun, Some(default_logger)); - } -} diff --git a/vnt/tun/src/windows/tun/wintun_raw.rs b/vnt/tun/src/windows/tun/wintun_raw.rs deleted file mode 100644 index e754bd5..0000000 --- a/vnt/tun/src/windows/tun/wintun_raw.rs +++ /dev/null @@ -1,449 +0,0 @@ -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] -/* automatically generated by rust-bindgen 0.59.1 */ -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit { - storage: Storage, -} -impl __BindgenBitfieldUnit { - #[inline] - pub const fn new(storage: Storage) -> Self { - Self { storage } - } -} -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - let bit_index = if cfg!(target_endian = "big") { - 7 - (index % 8) - } else { - index % 8 - }; - let mask = 1 << bit_index; - byte & mask == mask - } - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - let bit_index = if cfg!(target_endian = "big") { - 7 - (index % 8) - } else { - index % 8 - }; - let mask = 1 << bit_index; - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - let mut val = 0; - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - let index = if cfg!(target_endian = "big") { - bit_width as usize - 1 - i - } else { - i - }; - val |= 1 << index; - } - } - val - } - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - let index = if cfg!(target_endian = "big") { - bit_width as usize - 1 - i - } else { - i - }; - self.set_bit(index + bit_offset, val_bit_is_set); - } - } -} -pub type wchar_t = ::std::os::raw::c_ushort; -pub type DWORD = ::std::os::raw::c_ulong; -pub type BOOL = ::std::os::raw::c_int; -pub type BYTE = ::std::os::raw::c_uchar; -pub type ULONG64 = ::std::os::raw::c_ulonglong; -pub type DWORD64 = ::std::os::raw::c_ulonglong; -pub type WCHAR = wchar_t; -pub type LPCWSTR = *const WCHAR; -pub type HANDLE = *mut ::std::os::raw::c_void; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _GUID { - pub Data1: ::std::os::raw::c_ulong, - pub Data2: ::std::os::raw::c_ushort, - pub Data3: ::std::os::raw::c_ushort, - pub Data4: [::std::os::raw::c_uchar; 8usize], -} -#[test] -fn bindgen_test_layout__GUID() { - assert_eq!( - ::std::mem::size_of::<_GUID>(), - 16usize, - concat!("Size of: ", stringify!(_GUID)) - ); - assert_eq!( - ::std::mem::align_of::<_GUID>(), - 4usize, - concat!("Alignment of ", stringify!(_GUID)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_GUID>())).Data1 as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_GUID), - "::", - stringify!(Data1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_GUID>())).Data2 as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(_GUID), - "::", - stringify!(Data2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_GUID>())).Data3 as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(_GUID), - "::", - stringify!(Data3) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_GUID>())).Data4 as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_GUID), - "::", - stringify!(Data4) - ) - ); -} -pub type GUID = _GUID; -#[repr(C)] -#[derive(Copy, Clone)] -pub union _NET_LUID_LH { - pub Value: ULONG64, - pub Info: _NET_LUID_LH__bindgen_ty_1, -} -#[repr(C)] -#[repr(align(8))] -#[derive(Debug, Copy, Clone)] -pub struct _NET_LUID_LH__bindgen_ty_1 { - pub _bitfield_align_1: [u32; 0], - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, -} -#[test] -fn bindgen_test_layout__NET_LUID_LH__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<_NET_LUID_LH__bindgen_ty_1>(), - 8usize, - concat!("Size of: ", stringify!(_NET_LUID_LH__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<_NET_LUID_LH__bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(_NET_LUID_LH__bindgen_ty_1)) - ); -} -impl _NET_LUID_LH__bindgen_ty_1 { - #[inline] - pub fn Reserved(&self) -> ULONG64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u64) } - } - #[inline] - pub fn set_Reserved(&mut self, val: ULONG64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(0usize, 24u8, val as u64) - } - } - #[inline] - pub fn NetLuidIndex(&self) -> ULONG64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 24u8) as u64) } - } - #[inline] - pub fn set_NetLuidIndex(&mut self, val: ULONG64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(24usize, 24u8, val as u64) - } - } - #[inline] - pub fn IfType(&self) -> ULONG64 { - unsafe { ::std::mem::transmute(self._bitfield_1.get(48usize, 16u8) as u64) } - } - #[inline] - pub fn set_IfType(&mut self, val: ULONG64) { - unsafe { - let val: u64 = ::std::mem::transmute(val); - self._bitfield_1.set(48usize, 16u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - Reserved: ULONG64, - NetLuidIndex: ULONG64, - IfType: ULONG64, - ) -> __BindgenBitfieldUnit<[u8; 8usize]> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); - __bindgen_bitfield_unit.set(0usize, 24u8, { - let Reserved: u64 = unsafe { ::std::mem::transmute(Reserved) }; - Reserved as u64 - }); - __bindgen_bitfield_unit.set(24usize, 24u8, { - let NetLuidIndex: u64 = unsafe { ::std::mem::transmute(NetLuidIndex) }; - NetLuidIndex as u64 - }); - __bindgen_bitfield_unit.set(48usize, 16u8, { - let IfType: u64 = unsafe { ::std::mem::transmute(IfType) }; - IfType as u64 - }); - __bindgen_bitfield_unit - } -} -#[test] -fn bindgen_test_layout__NET_LUID_LH() { - assert_eq!( - ::std::mem::size_of::<_NET_LUID_LH>(), - 8usize, - concat!("Size of: ", stringify!(_NET_LUID_LH)) - ); - assert_eq!( - ::std::mem::align_of::<_NET_LUID_LH>(), - 8usize, - concat!("Alignment of ", stringify!(_NET_LUID_LH)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Value as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_NET_LUID_LH), - "::", - stringify!(Value) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Info as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_NET_LUID_LH), - "::", - stringify!(Info) - ) - ); -} -pub type NET_LUID_LH = _NET_LUID_LH; -pub type NET_LUID = NET_LUID_LH; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _WINTUN_ADAPTER { - _unused: [u8; 0], -} -#[doc = " A handle representing Wintun adapter"] -pub type WINTUN_ADAPTER_HANDLE = *mut _WINTUN_ADAPTER; -#[doc = "< Informational"] -pub const WINTUN_LOGGER_LEVEL_WINTUN_LOG_INFO: WINTUN_LOGGER_LEVEL = 0; -#[doc = "< Warning"] -pub const WINTUN_LOGGER_LEVEL_WINTUN_LOG_WARN: WINTUN_LOGGER_LEVEL = 1; -#[doc = "< Error"] -pub const WINTUN_LOGGER_LEVEL_WINTUN_LOG_ERR: WINTUN_LOGGER_LEVEL = 2; -#[doc = " Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK."] -pub type WINTUN_LOGGER_LEVEL = ::std::os::raw::c_int; -#[doc = " Called by internal logger to report diagnostic messages"] -#[doc = ""] -#[doc = " @param Level Message level."] -#[doc = ""] -#[doc = " @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC."] -#[doc = ""] -#[doc = " @param Message Message text."] -pub type WINTUN_LOGGER_CALLBACK = ::std::option::Option< - unsafe extern "C" fn(Level: WINTUN_LOGGER_LEVEL, Timestamp: DWORD64, Message: LPCWSTR), ->; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _TUN_SESSION { - _unused: [u8; 0], -} -#[doc = " A handle representing Wintun session"] -pub type WINTUN_SESSION_HANDLE = *mut _TUN_SESSION; -extern crate libloading; -pub struct wintun { - __library: ::libloading::Library, - pub WintunCreateAdapter: unsafe extern "C" fn( - arg1: LPCWSTR, - arg2: LPCWSTR, - arg3: *const GUID, - ) -> WINTUN_ADAPTER_HANDLE, - pub WintunCloseAdapter: unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE), - pub WintunOpenAdapter: unsafe extern "C" fn(arg1: LPCWSTR) -> WINTUN_ADAPTER_HANDLE, - pub WintunGetAdapterLUID: - unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: *mut NET_LUID), - pub WintunGetRunningDriverVersion: unsafe extern "C" fn() -> DWORD, - pub WintunDeleteDriver: unsafe extern "C" fn() -> BOOL, - pub WintunSetLogger: unsafe extern "C" fn(arg1: WINTUN_LOGGER_CALLBACK), - pub WintunStartSession: - unsafe extern "C" fn(arg1: WINTUN_ADAPTER_HANDLE, arg2: DWORD) -> WINTUN_SESSION_HANDLE, - pub WintunEndSession: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE), - pub WintunGetReadWaitEvent: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE) -> HANDLE, - pub WintunReceivePacket: - unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *mut DWORD) -> *mut BYTE, - pub WintunReleaseReceivePacket: - unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE), - pub WintunAllocateSendPacket: - unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: DWORD) -> *mut BYTE, - pub WintunSendPacket: unsafe extern "C" fn(arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE), -} -impl wintun { - pub unsafe fn new

(path: P) -> Result - where - P: AsRef<::std::ffi::OsStr>, - { - let library = ::libloading::Library::new(path)?; - Self::from_library(library) - } - pub unsafe fn from_library(library: L) -> Result - where - L: Into<::libloading::Library>, - { - let __library = library.into(); - let WintunCreateAdapter = __library.get(b"WintunCreateAdapter\0").map(|sym| *sym)?; - let WintunCloseAdapter = __library.get(b"WintunCloseAdapter\0").map(|sym| *sym)?; - let WintunOpenAdapter = __library.get(b"WintunOpenAdapter\0").map(|sym| *sym)?; - let WintunGetAdapterLUID = __library.get(b"WintunGetAdapterLUID\0").map(|sym| *sym)?; - let WintunGetRunningDriverVersion = __library - .get(b"WintunGetRunningDriverVersion\0") - .map(|sym| *sym)?; - let WintunDeleteDriver = __library.get(b"WintunDeleteDriver\0").map(|sym| *sym)?; - let WintunSetLogger = __library.get(b"WintunSetLogger\0").map(|sym| *sym)?; - let WintunStartSession = __library.get(b"WintunStartSession\0").map(|sym| *sym)?; - let WintunEndSession = __library.get(b"WintunEndSession\0").map(|sym| *sym)?; - let WintunGetReadWaitEvent = __library.get(b"WintunGetReadWaitEvent\0").map(|sym| *sym)?; - let WintunReceivePacket = __library.get(b"WintunReceivePacket\0").map(|sym| *sym)?; - let WintunReleaseReceivePacket = __library - .get(b"WintunReleaseReceivePacket\0") - .map(|sym| *sym)?; - let WintunAllocateSendPacket = __library - .get(b"WintunAllocateSendPacket\0") - .map(|sym| *sym)?; - let WintunSendPacket = __library.get(b"WintunSendPacket\0").map(|sym| *sym)?; - Ok(wintun { - __library, - WintunCreateAdapter, - WintunCloseAdapter, - WintunOpenAdapter, - WintunGetAdapterLUID, - WintunGetRunningDriverVersion, - WintunDeleteDriver, - WintunSetLogger, - WintunStartSession, - WintunEndSession, - WintunGetReadWaitEvent, - WintunReceivePacket, - WintunReleaseReceivePacket, - WintunAllocateSendPacket, - WintunSendPacket, - }) - } - pub unsafe fn WintunCreateAdapter( - &self, - arg1: LPCWSTR, - arg2: LPCWSTR, - arg3: *const GUID, - ) -> WINTUN_ADAPTER_HANDLE { - (self.WintunCreateAdapter)(arg1, arg2, arg3) - } - pub unsafe fn WintunCloseAdapter(&self, arg1: WINTUN_ADAPTER_HANDLE) -> () { - (self.WintunCloseAdapter)(arg1) - } - pub unsafe fn WintunOpenAdapter(&self, arg1: LPCWSTR) -> WINTUN_ADAPTER_HANDLE { - (self.WintunOpenAdapter)(arg1) - } - pub unsafe fn WintunGetAdapterLUID( - &self, - arg1: WINTUN_ADAPTER_HANDLE, - arg2: *mut NET_LUID, - ) -> () { - (self.WintunGetAdapterLUID)(arg1, arg2) - } - pub unsafe fn WintunGetRunningDriverVersion(&self) -> DWORD { - (self.WintunGetRunningDriverVersion)() - } - pub unsafe fn WintunDeleteDriver(&self) -> BOOL { - (self.WintunDeleteDriver)() - } - pub unsafe fn WintunSetLogger(&self, arg1: WINTUN_LOGGER_CALLBACK) -> () { - (self.WintunSetLogger)(arg1) - } - pub unsafe fn WintunStartSession( - &self, - arg1: WINTUN_ADAPTER_HANDLE, - arg2: DWORD, - ) -> WINTUN_SESSION_HANDLE { - (self.WintunStartSession)(arg1, arg2) - } - pub unsafe fn WintunEndSession(&self, arg1: WINTUN_SESSION_HANDLE) -> () { - (self.WintunEndSession)(arg1) - } - pub unsafe fn WintunGetReadWaitEvent(&self, arg1: WINTUN_SESSION_HANDLE) -> HANDLE { - (self.WintunGetReadWaitEvent)(arg1) - } - pub unsafe fn WintunReceivePacket( - &self, - arg1: WINTUN_SESSION_HANDLE, - arg2: *mut DWORD, - ) -> *mut BYTE { - (self.WintunReceivePacket)(arg1, arg2) - } - pub unsafe fn WintunReleaseReceivePacket( - &self, - arg1: WINTUN_SESSION_HANDLE, - arg2: *const BYTE, - ) -> () { - (self.WintunReleaseReceivePacket)(arg1, arg2) - } - pub unsafe fn WintunAllocateSendPacket( - &self, - arg1: WINTUN_SESSION_HANDLE, - arg2: DWORD, - ) -> *mut BYTE { - (self.WintunAllocateSendPacket)(arg1, arg2) - } - pub unsafe fn WintunSendPacket(&self, arg1: WINTUN_SESSION_HANDLE, arg2: *const BYTE) -> () { - (self.WintunSendPacket)(arg1, arg2) - } -}