diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2019-09-30 12:26:23 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2019-09-30 14:50:37 +0100 |
| commit | a28b7f1a8720219a5e9416d77c3e8ea780fb2189 (patch) | |
| tree | 1bd71b894c513d75de0d8b7cecf500f038e4783d | |
| parent | 3164047b1eae8ce7fb4e10f89f86c4a39158576b (diff) | |
| download | mullvadvpn-a28b7f1a8720219a5e9416d77c3e8ea780fb2189.tar.xz mullvadvpn-a28b7f1a8720219a5e9416d77c3e8ea780fb2189.zip | |
Add Windows implementation for ping_monitor
| -rw-r--r-- | Cargo.lock | 125 | ||||
| -rw-r--r-- | talpid-core/Cargo.toml | 4 | ||||
| -rw-r--r-- | talpid-core/src/lib.rs | 1 | ||||
| -rw-r--r-- | talpid-core/src/ping_monitor/mod.rs | 2 | ||||
| -rw-r--r-- | talpid-core/src/ping_monitor/win.rs | 157 |
5 files changed, 288 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock index 74dec12dda..0c28150f5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,11 @@ dependencies = [ [[package]] name = "bitflags" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -664,6 +669,11 @@ dependencies = [ ] [[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "globset" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1697,6 +1707,41 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "pnet_base" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pnet_macros" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_macros_support" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pnet_packet" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_macros 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_macros_support 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "ppv-lite86" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2035,6 +2080,11 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2266,6 +2316,51 @@ dependencies = [ ] [[package]] +name = "syntex" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_errors" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_pos" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_syntax" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "system-configuration" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2318,10 +2413,13 @@ dependencies = [ "os_pipe 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "pfctl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pnet_packet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rtnetlink 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "system-configuration 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "talpid-ipc 0.1.0", "talpid-types 0.1.0", @@ -2404,6 +2502,15 @@ dependencies = [ ] [[package]] +name = "term" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "termcolor" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2772,6 +2879,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-xid" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3016,6 +3128,7 @@ dependencies = [ "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" @@ -3077,6 +3190,7 @@ dependencies = [ "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d069fe6beb9be359ef505650b3f73228c5591a3c4b1f32be2f4f44459ffa3a" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" @@ -3161,6 +3275,10 @@ dependencies = [ "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pfctl 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4410511aea78cbc7b1d192315034607be78537336590ebfc7fc92496768c45af" "checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" +"checksum pnet_base 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df28acf2fcc77436dd2b91a9a0c2bb617f9ca5f2acefee1a4135058b9f9801f" +"checksum pnet_macros 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d228096fd739d4e3e60dee9e1e4f07d9ae0f3f309c876834192538748e561e4" +"checksum pnet_macros_support 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84684f2cddefc37a06f2fe2ca4dcc3457fc3b282734b5246507d8ee75d2780ae" +"checksum pnet_packet 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a6cdcdaddc5174f18286298842a4e31cd3cc018933d42af51434b1fa07dcbe" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" @@ -3200,6 +3318,7 @@ dependencies = [ "checksum rtnetlink 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)" = "<none>" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" @@ -3232,10 +3351,15 @@ dependencies = [ "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317" +"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646" +"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6" +"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d" "checksum system-configuration 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ce91c23e42859a5b8a7da032096d34f776512239e89de6c7bec817d6089cf9c" "checksum system-configuration-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "114702b56796b5cf377b6ae266a319fa687edd4d9f18f4d5658193e65dcaf006" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -3269,6 +3393,7 @@ dependencies = [ "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index ad033f2ce3..1ccf689a0b 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -63,7 +63,9 @@ tun = "0.4.3" widestring = "0.4" winreg = "0.6" winapi = { version = "0.3.6", features = ["handleapi", "libloaderapi", "synchapi", "winbase", "winuser"] } - +socket2 = "0.3" +rand = "0.7" +pnet_packet = "0.22" [dev-dependencies] tempfile = "3.0" diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs index cd88277d9d..5fdbd3030d 100644 --- a/talpid-core/src/lib.rs +++ b/talpid-core/src/lib.rs @@ -23,6 +23,7 @@ mod winnet; #[cfg(any(target_os = "linux", target_os = "macos"))] /// Working with IP interface devices pub mod network_interface; +#[cfg(not(windows))] /// Abstraction over operating system routing table. pub mod routing; diff --git a/talpid-core/src/ping_monitor/mod.rs b/talpid-core/src/ping_monitor/mod.rs index 25b33be0bb..8cdc766ad4 100644 --- a/talpid-core/src/ping_monitor/mod.rs +++ b/talpid-core/src/ping_monitor/mod.rs @@ -2,6 +2,8 @@ #[path = "unix.rs"] mod imp; + +#[cfg(target_os = "windows")] #[path = "win.rs"] mod imp; diff --git a/talpid-core/src/ping_monitor/win.rs b/talpid-core/src/ping_monitor/win.rs new file mode 100644 index 0000000000..e98161fae6 --- /dev/null +++ b/talpid-core/src/ping_monitor/win.rs @@ -0,0 +1,157 @@ +#![allow(dead_code)] +// TODO: Remove lint exemption once ping monitor is used on Windows +use pnet_packet::{ + icmp::{ + self, + echo_reply::EchoReplyPacket, + echo_request::{EchoRequestPacket, MutableEchoRequestPacket}, + IcmpCode, IcmpPacket, IcmpType, + }, + Packet, +}; +use socket2::{Domain, Protocol, Socket, Type}; +use std::{ + io, + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::mpsc, + thread, + time::{Duration, Instant}, +}; + +#[derive(err_derive::Error, Debug)] +pub enum Error { + /// Failed to open raw socket + #[error(display = "Failed to open raw socket")] + OpenError(#[error(cause)] io::Error), + + /// Failed to read from raw socket + #[error(display = "Failed to read from socket")] + ReadError(#[error(cause)] io::Error), + + /// Failed to write to raw socket + #[error(display = "Failed to write to socket")] + WriteError(#[error(cause)] io::Error), + + #[error(display = "Timed out")] + TimeoutError, +} + +pub fn monitor_ping( + ip: Ipv4Addr, + timeout_secs: u16, + _interface: &str, + close_receiver: mpsc::Receiver<()>, +) -> Result<()> { + let mut pinger = Pinger::new(ip)?; + while let Err(mpsc::TryRecvError::Empty) = close_receiver.try_recv() { + let start = Instant::now(); + pinger.send_ping(Duration::from_secs(timeout_secs.into()))?; + if let Some(remaining) = + Duration::from_secs(timeout_secs.into()).checked_sub(start.elapsed()) + { + thread::sleep(remaining); + } + } + + Ok(()) +} + +pub fn ping(ip: Ipv4Addr, timeout_secs: u16, _interface: &str) -> Result<()> { + Pinger::new(ip)?.send_ping(Duration::from_secs(timeout_secs.into())) +} + +type Result<T> = std::result::Result<T, Error>; + +pub struct Pinger { + sock: Socket, + addr: Ipv4Addr, + id: u16, + seq: u16, +} + +impl Pinger { + pub fn new(addr: Ipv4Addr) -> Result<Self> { + let sock = Socket::new(Domain::ipv4(), Type::raw(), Some(Protocol::icmpv4())) + .map_err(Error::OpenError)?; + sock.set_nonblocking(true).map_err(Error::OpenError)?; + Ok(Self { + sock, + id: rand::random(), + addr, + seq: 0, + }) + } + + /// Sends an ICMP echo request + pub fn send_ping(&mut self, timeout: Duration) -> Result<()> { + let dest = SocketAddr::new(IpAddr::from(self.addr), 0); + let request = self.next_ping_request(); + self.sock + .send_to(request.packet(), &dest.into()) + .map_err(Error::WriteError)?; + self.wait_for_response(Instant::now() + timeout, &request) + } + + /// returns the next ping packet + fn next_ping_request(&mut self) -> EchoRequestPacket<'static> { + const ICMP_HEADER_LENGTH: usize = 8; + const ICMP_PAYLOAD_LENGTH: usize = 24; + const ICMP_PACKET_LENGTH: usize = ICMP_HEADER_LENGTH + ICMP_PAYLOAD_LENGTH; + let payload: [u8; ICMP_PAYLOAD_LENGTH] = rand::random(); + let mut packet = MutableEchoRequestPacket::owned(vec![0u8; ICMP_PACKET_LENGTH]) + .expect("Failed to construct an empty packet"); + packet.set_icmp_type(IcmpType::new(8)); + packet.set_icmp_code(IcmpCode::new(0)); + packet.set_sequence_number(self.next_seq()); + packet.set_identifier(self.id); + packet.set_payload(&payload); + packet.set_checksum(icmp::checksum(&IcmpPacket::new(&packet.packet()).unwrap())); + packet.consume_to_immutable() + } + + fn next_seq(&mut self) -> u16 { + let seq = self.seq; + self.seq += 1; + seq + } + + + fn wait_for_response(&mut self, deadline: Instant, req: &EchoRequestPacket<'_>) -> Result<()> { + let mut recv_buffer = [0u8; 4096]; + while Instant::now() < deadline { + match self.sock.recv(&mut recv_buffer) { + Ok(recv_len) => { + if recv_len > 20 { + // have to slice off first 20 bytes for the IP header. + if let Some(reply) = Self::parse_response(&recv_buffer[20..recv_len]) { + if reply.get_identifier() == req.get_identifier() + && reply.get_sequence_number() == req.get_sequence_number() + && req.payload() == reply.payload() + { + return Ok(()); + } + } + } + } + Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + std::thread::sleep(Duration::from_millis(100)); + continue; + } + Err(e) => { + return Err(Error::ReadError(e)); + } + } + } + Err(Error::TimeoutError) + } + + fn parse_response<'a>(buffer: &'a [u8]) -> Option<EchoReplyPacket<'a>> { + let icmp_checksum = icmp::checksum(&IcmpPacket::new(buffer)?); + let reply = EchoReplyPacket::new(buffer)?; + if reply.get_checksum() == icmp_checksum { + Some(reply) + } else { + None + } + } +} |
