From 20caf209bdc9e04c22b25e651faf87fc37ea6d06 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 18 Nov 2024 23:30:12 -0800 Subject: [PATCH] Fix delays in pcap implementation --- vsock-proxy/Cargo.lock | 336 +++++++---------------- vsock-proxy/parent/Cargo.toml | 5 +- vsock-proxy/parent/src/packet_capture.rs | 194 ++++++------- 3 files changed, 184 insertions(+), 351 deletions(-) diff --git a/vsock-proxy/Cargo.lock b/vsock-proxy/Cargo.lock index 45925620..5fdcf103 100644 --- a/vsock-proxy/Cargo.lock +++ b/vsock-proxy/Cargo.lock @@ -35,7 +35,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -70,31 +70,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - [[package]] name = "async-io" version = "1.6.0" @@ -111,27 +86,7 @@ dependencies = [ "slab", "socket2", "waker-fn", - "winapi 0.3.9", -] - -[[package]] -name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-net" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5373304df79b9b4395068fb080369ec7178608827306ce4d081cba51cac551df" -dependencies = [ - "async-io", - "blocking", - "futures-lite", + "winapi", ] [[package]] @@ -148,7 +103,7 @@ dependencies = [ "libc", "once_cell", "signal-hook", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -182,7 +137,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -380,7 +335,7 @@ dependencies = [ "serde", "time", "wasm-bindgen", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -723,7 +678,7 @@ checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ "errno-dragonfly", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -786,22 +741,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "futures" version = "0.1.31" @@ -1027,7 +966,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1131,16 +1070,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "language-tags" version = "0.2.2" @@ -1173,22 +1102,22 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.9", + "winapi", ] [[package]] name = "libloading" -version = "0.7.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.9", + "windows-targets", ] [[package]] @@ -1330,25 +1259,6 @@ dependencies = [ "log 0.3.9", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.14", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.8.4" @@ -1361,18 +1271,6 @@ dependencies = [ "windows-sys 0.36.1", ] -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -1391,17 +1289,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "netlink-packet-core" version = "0.2.4" @@ -1547,7 +1434,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1666,7 +1553,6 @@ dependencies = [ "nix 0.26.2", "parent_lib", "pcap", - "pcap-async", "rtnetlink", "shared", "tempdir", @@ -1698,44 +1584,18 @@ checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" [[package]] name = "pcap" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742d671d505d54e83924cc200e08442111f0ace8ebee3b9dc31cd9710cb301cb" +version = "2.2.0" +source = "git+https://github.com/fortanix/pcap.git?branch=main#f72d7eed74bae6619bea2a0170922f5eb6ff610e" dependencies = [ + "bitflags", "errno", - "libc", - "libloading 0.6.7", - "regex 1.5.4", - "widestring", - "winapi 0.3.9", -] - -[[package]] -name = "pcap-async" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eda74213b53444b5f11f0c96fca2e17b9c5c2d51e02ee4f5e89d6a8865f3c91" -dependencies = [ - "byteorder", "futures 0.3.16", "libc", - "log 0.4.14", - "mio 0.6.23", - "pcap-sys", - "pin-project", - "smol", - "thiserror", -] - -[[package]] -name = "pcap-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114725dfe222c031086765fc138cf20291840ee1290883bcfacaca5f226289a3" -dependencies = [ - "libc", + "libloading 0.8.5", "pkg-config", - "winapi 0.3.9", + "regex 1.5.4", + "tokio", + "windows-sys 0.36.1", ] [[package]] @@ -1762,26 +1622,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" -[[package]] -name = "pin-project" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.7" @@ -1825,7 +1665,7 @@ dependencies = [ "libc", "log 0.4.14", "wepoll-ffi", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1868,7 +1708,7 @@ dependencies = [ "libc", "rand_core 0.3.1", "rdrand", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1887,7 +1727,7 @@ dependencies = [ "rand_os", "rand_pcg", "rand_xorshift", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1971,7 +1811,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1985,7 +1825,7 @@ dependencies = [ "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2092,7 +1932,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2349,24 +2189,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" -[[package]] -name = "smol" -version = "1.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4" -dependencies = [ - "async-channel", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-net", - "async-process", - "blocking", - "futures-lite", - "once_cell", -] - [[package]] name = "socket2" version = "0.4.7" @@ -2374,7 +2196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2412,7 +2234,7 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2436,7 +2258,7 @@ dependencies = [ "rand 0.8.5", "redox_syscall", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2502,7 +2324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2530,13 +2352,13 @@ dependencies = [ "bytes 1.0.1", "libc", "memchr", - "mio 0.8.4", + "mio", "num_cpus", "once_cell", "pin-project-lite", "socket2", "tokio-macros", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2841,18 +2663,6 @@ dependencies = [ "libc", ] -[[package]] -name = "widestring" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2863,12 +2673,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2881,7 +2685,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2909,21 +2713,43 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.1", "windows_aarch64_msvc 0.42.1", "windows_i686_gnu 0.42.1", "windows_i686_msvc 0.42.1", "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.1", "windows_x86_64_msvc 0.42.1", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" @@ -2936,6 +2762,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -2948,6 +2780,18 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -2960,6 +2804,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -2972,12 +2822,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -2991,14 +2853,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "yasna" diff --git a/vsock-proxy/parent/Cargo.toml b/vsock-proxy/parent/Cargo.toml index 55025f07..91be8d6f 100644 --- a/vsock-proxy/parent/Cargo.toml +++ b/vsock-proxy/parent/Cargo.toml @@ -19,12 +19,11 @@ futures = "0.3" ipnetwork = { version = "0.18.0", features = ["serde"] } log = "0.4" nix = { version = "0.26.1", features = ["hostname"] } -pcap = "0.9.1" -pcap-async = "0.4.1" +pcap = { version = "2.2.0", git = "https://github.com/fortanix/pcap.git", branch = "main", features = ["capture-stream"] } rtnetlink = "0.8.0" shared = { path = "../shared" } tempdir = "0.3.7" tokio = { version = "1.21.1", features = ["macros", "rt", "rt-multi-thread", "io-std", "io-util"] } tokio-vsock = "0.3.1" tun = {version = "0.5.3" ,features = ["async"] } -parent_lib = { path = "lib" } \ No newline at end of file +parent_lib = { path = "lib" } diff --git a/vsock-proxy/parent/src/packet_capture.rs b/vsock-proxy/parent/src/packet_capture.rs index 488384f9..7e8b4549 100644 --- a/vsock-proxy/parent/src/packet_capture.rs +++ b/vsock-proxy/parent/src/packet_capture.rs @@ -5,15 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use std::collections::HashSet; -use std::sync::mpsc; -use std::sync::mpsc::TryRecvError; -use std::thread; -use futures::stream::Fuse; -use futures::StreamExt; +use futures::{SinkExt, StreamExt}; use log::{info, warn}; -use pcap::{Active, Capture, Device}; -use pcap_async::{Config, Handle}; +use pcap::{Active, Capture, Device, Direction, Packet, PacketCodec}; use shared::socket::{AsyncReadLvStream, AsyncWriteLvStream}; use tokio::io; use tokio::io::{ReadHalf, WriteHalf}; @@ -34,8 +29,8 @@ pub(crate) struct PcapLoopsResult { /// # Returns /// Handles to two network forwarding tasks pub(crate) fn start_pcap_loops(network_device: Device, vsock: AsyncVsockStream) -> Result { - let read_capture = open_async_packet_capture(&network_device.name)?; - let write_capture = open_packet_capture(network_device)?; + let read_capture = open_packet_capture(network_device.clone(), Mode::Read)?; + let write_capture = open_packet_capture(network_device, Mode::Write)?; let (vsock_read, vsock_write) = io::split(vsock); @@ -50,130 +45,111 @@ pub(crate) fn start_pcap_loops(network_device: Device, vsock: AsyncVsockStream) } async fn read_from_device_async( - mut capture: Fuse, + capture: Capture, mut enclave_stream: WriteHalf, ) -> Result<(), String> { - let mut unsupported_protocols = HashSet::::new(); + struct Raw; - loop { - let packets = match capture.next().await { - Some(Ok(packets)) => packets, - Some(Err(e)) => return Err(format!("Failed to read packet from pcap {:?}", e)), - None => return Ok(()), - }; - - for packet in packets { - if packet.actual_length() == packet.original_length() { - let mut data = packet.into_data(); - - match recompute_packet_checksum(&mut data) { - Err(ChecksumComputationError::Err(err)) => { - warn!("Failed recomputing checksum for a packet. {:?}", err); - } - Err(ChecksumComputationError::UnsupportedProtocol(protocol)) => { - if unsupported_protocols.insert(protocol) { - warn!( - "Unsupported protocol {} encountered when recomputing checksum for a packet.", - protocol - ); - } - } - _ => {} - } + impl PacketCodec for Raw { + type Item = Result, String>; - enclave_stream.write_lv_bytes(&data).await?; + fn decode(&mut self, packet: Packet) -> Self::Item { + if packet.header.caplen == packet.header.len { + Ok(packet.data.to_owned()) } else { - warn!( + Err(format!( "Dropped PCAP captured packet! \ Reason: captured packet length ({} bytes) \ is different than the inbound packet length ({} bytes).", - packet.actual_length(), - packet.original_length() - ); + packet.header.caplen, + packet.header.len + )) } } } -} -async fn write_to_device_async( - mut capture: Capture, - mut from_enclave: ReadHalf, -) -> Result<(), String> { - let (packet_tx, packet_rx) = mpsc::channel(); - let (error_tx, error_rx) = mpsc::sync_channel(1); - - // This is a fix to avoid blocking when writing packets to pcap, - // as there is no async write function available in pcap crate. - thread::spawn(move || { - while let Ok(packet) = packet_rx.recv() { - if let Err(e) = capture.sendpacket(packet) { - let err = format!("Failed to write to pcap {:?}", e); - - error_tx.send(err).expect("Failed sending error"); + let mut unsupported_protocols = HashSet::::new(); - break; + let mut capture = capture.stream(Raw) + .map_err(|err| format!("Failed to convert capture to stream: {:?}", err))?; + + while let Some(pkt) = capture.next().await { + if let Err(err) = async { + let mut data = pkt.map_err(|err| format!("error reading from pcap device: {:?}", err))??; + match recompute_packet_checksum(&mut data) { + Err(ChecksumComputationError::UnsupportedProtocol(protocol)) => { + if unsupported_protocols.insert(protocol) { + warn!( + "Unsupported protocol {} encountered when recomputing checksum for a packet.", + protocol + ); + } + } + Err(ChecksumComputationError::Err(err)) => { + return Err(format!("error recomputing packet checksum: {:?}", err)); + } + Ok(_) => {} } - } - }); - loop { - let packet = from_enclave - .read_lv_bytes() - .await - .map_err(|err| format!("Failed to read packet from enclave {:?}", err))?; - - match error_rx.try_recv() { - Err(TryRecvError::Disconnected) => { - return Err(format!("pcap writer thread died prematurely")); - } - Ok(e) => return Err(e), - _ => {} + enclave_stream.write_lv_bytes(&data).await + .map_err(|err| format!("error writing to vsock {:?}", err)) + }.await { + warn!("Failed to process packet towards enclave: {}", err); } + }; - packet_tx - .send(packet) - .map_err(|err| format!("Failed to send packet to pcap writer thread {:?}", err))?; - } + Ok(()) } -fn open_packet_capture(device: pcap::Device) -> Result, String> { - let device_name = device.name.clone(); - let capture = Capture::from_device(device).map_err(|err| format!("Cannot create capture {:?}", err))?; - - info!("Capturing with device: {}", device_name); - - capture.open().map_err(|err| format!("Cannot open capture {:?}", err)) +async fn write_to_device_async( + capture: Capture, + mut from_enclave: ReadHalf, +) -> Result<(), String> { + let mut capture = capture.sink() + .map_err(|err| format!("Failed to convert capture to sink: {:?}", err))?; + loop { + if let Err(err) = async { + let packet = from_enclave + .read_lv_bytes() + .await + .map_err(|err| format!("error reading from vsock: {:?}", err))?; + + capture.send(packet).await + .map_err(|err| format!("error writing to pcap device: {:?}", err)) + }.await { + warn!("Failed to process packet from enclave: {}", err); + } + } } -fn open_async_packet_capture(device_name: &str) -> Result, String> { - let config = async_packet_capture_config(); - - let handle = Handle::live_capture(device_name) - .map_err(|err| format!("Cannot create capture for device {}, error: {:?}", device_name, err))?; - - handle - .set_immediate_mode() - .map_err(|err| format!("Failed to set pcap immediate mode {:?}", err))?; - - pcap_async::PacketStream::new(config, handle) - .map(|e| e.fuse()) - .map_err(|err| format!("Cannot open async capture {:?}", err)) +enum Mode { + Read, + Write, } -fn async_packet_capture_config() -> Config { - let mut config = Config::default(); +fn open_packet_capture(device: pcap::Device, mode: Mode) -> Result, String> { + let device_name = device.name.clone(); + let capture = Capture::from_device(device).map_err(|err| format!("Cannot create capture {:?}", err))? + .immediate_mode(true); - config.with_blocking(false); + if let Mode::Read = mode { + info!("Capturing with device: {}", device_name); + } - // We capture only incoming packets inside the parent, however by default pcap - // captures all the packets that come through the network device (like - // tcpdump). Without this filter what would happen is that pcap will capture - // packets forwarded from enclave's TAP device, which in turn - // will get forwarded back into the enclave by the parent. - // This doesn't break the networking as incorrect packets will get dropped by - // the enclave, but that way it generates unnecessary traffic that we don't - // need. - config.with_bpf("inbound".to_string()); + let mut capture = capture.open().map_err(|err| format!("Cannot open capture {:?}", err))?; + capture = capture.setnonblock().map_err(|err| format!("Failed to configure pcap non-blocking mode {:?}", err))?; + + if let Mode::Read = mode { + // We capture only incoming packets inside the parent, however by default pcap + // captures all the packets that come through the network device (like + // tcpdump). Without this filter what would happen is that pcap will capture + // packets forwarded from enclave's TAP device, which in turn + // will get forwarded back into the enclave by the parent. + // This doesn't break the networking as incorrect packets will get dropped by + // the enclave, but that way it generates unnecessary traffic that we don't + // need. + capture.direction(Direction::In).map_err(|err| format!("Failed to set pcap capture directoin {:?}", err))?; + } - config + Ok(capture) }