diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11ae6125..682056a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,8 +120,9 @@ jobs: - name: Copy wintun.dll to current dir if: startsWith(matrix.build, 'windows') shell: bash + # The simulation tests run from the crates/trippy-core directory and so `wintun.dll` needs to be copied there run: | - cp "tests/resources/wintun.dll" "." + cp "crates/trippy-core/tests/resources/wintun.dll" "./crates/trippy-core/" - name: Allow ICMPv4 and ICMPv6 in Windows defender firewall if: startsWith(matrix.build, 'windows') shell: pwsh @@ -195,5 +196,11 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: install cargo-msrv run: cargo install --git https://github.com/foresterre/cargo-msrv.git cargo-msrv - - name: check msrv - run: cargo msrv --output-format json verify -- cargo check \ No newline at end of file + - name: check msrv for trippy + run: cargo msrv verify --output-format json --manifest-path crates/trippy/Cargo.toml -- cargo check + - name: check msrv for trippy-core + run: cargo msrv verify --output-format json --manifest-path crates/trippy-core/Cargo.toml -- cargo check + - name: check msrv for trippy-dns + run: cargo msrv verify --output-format json --manifest-path crates/trippy-dns/Cargo.toml -- cargo check + - name: check msrv for trippy-privilege + run: cargo msrv verify --output-format json --manifest-path crates/trippy-privilege/Cargo.toml -- cargo check \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af448f01..cc7921cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -151,7 +151,7 @@ jobs: if: startsWith(matrix.build, 'x86_64-linux-gnu') run: | cargo install cargo-generate-rpm - cargo generate-rpm --target ${{ matrix.target }} -o target/${{ matrix.target }}/generate-rpm/trippy-${{ needs.create-release.outputs.trip_version }}-x86_64.rpm + cargo generate-rpm -p crates/trippy --target ${{ matrix.target }} -o target/${{ matrix.target }}/generate-rpm/trippy-${{ needs.create-release.outputs.trip_version }}-x86_64.rpm - name: Upload RPM package if: startsWith(matrix.build, 'x86_64-linux-gnu') diff --git a/Cargo.lock b/Cargo.lock index 3e396d61..604746c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "27a4bd113ab6da4cd0f521068a6e2ee1065eab54107266a11835d02c8ec86a37" [[package]] name = "arrayvec" @@ -128,7 +128,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -292,7 +292,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -470,7 +470,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -481,7 +481,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -537,9 +537,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "encoding_rs" @@ -568,7 +568,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -947,9 +947,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" @@ -969,9 +969,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -1051,9 +1051,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -1094,7 +1094,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1453,22 +1453,22 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1518,7 +1518,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1605,7 +1605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1639,7 +1639,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1655,9 +1655,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.62" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f660c3bfcefb88c538776b6685a0c472e3128b51e74d48793dc2a488196e8eb" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", @@ -1698,7 +1698,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1709,28 +1709,28 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", "test-case-core", ] [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1816,7 +1816,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1885,7 +1885,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] [[package]] @@ -1956,55 +1956,94 @@ name = "trippy" version = "0.11.0-dev" dependencies = [ "anyhow", - "arrayvec", - "bitflags", - "caps", "chrono", "clap", "clap_complete", "clap_mangen", "comfy-table", - "crossbeam", "crossterm", "csv", "derive_more", - "dns-lookup", "encoding_rs_io", "etcetera", - "hex-literal", - "hickory-resolver", "humantime", "indexmap 2.2.6", - "ipnetwork", "itertools", "maxminddb", - "mockall", - "nix", "parking_lot", - "paste", "petgraph", "pretty_assertions", - "rand", "ratatui", "serde", "serde_json", "serde_with", "serde_yaml", - "socket2", "strum", "test-case", "thiserror", - "tokio", - "tokio-util", "toml", "tracing", "tracing-chrome", "tracing-subscriber", + "trippy-core", + "trippy-dns", + "trippy-privilege", +] + +[[package]] +name = "trippy-core" +version = "0.11.0-dev" +dependencies = [ + "anyhow", + "arrayvec", + "bitflags", + "derive_more", + "hex-literal", + "ipnetwork", + "itertools", + "mockall", + "nix", + "paste", + "rand", + "serde", + "serde_yaml", + "socket2", + "test-case", + "thiserror", + "tokio", + "tokio-util", + "tracing", + "tracing-subscriber", "tun2", "widestring", "windows-sys 0.52.0", ] +[[package]] +name = "trippy-dns" +version = "0.11.0-dev" +dependencies = [ + "anyhow", + "crossbeam", + "dns-lookup", + "hickory-resolver", + "itertools", + "parking_lot", + "thiserror", +] + +[[package]] +name = "trippy-privilege" +version = "0.11.0-dev" +dependencies = [ + "anyhow", + "caps", + "nix", + "paste", + "thiserror", + "windows-sys 0.52.0", +] + [[package]] name = "tun2" version = "1.3.0" @@ -2119,7 +2158,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", "wasm-bindgen-shared", ] @@ -2141,7 +2180,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2393,5 +2432,5 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.62", + "syn 2.0.64", ] diff --git a/Cargo.toml b/Cargo.toml index e21e0a78..f8dd38cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,107 +1,25 @@ -[package] -name = "trippy" +[workspace] +resolver = "2" +members = ["crates/trippy", "crates/trippy-core", "crates/trippy-privilege", "crates/trippy-dns"] + +[workspace.package] version = "0.11.0-dev" authors = ["FujiApple "] -description = "A network diagnostic tool" documentation = "https://github.com/fujiapple852/trippy" homepage = "https://github.com/fujiapple852/trippy" repository = "https://github.com/fujiapple852/trippy" -keywords = ["cli", "tui", "traceroute", "ping", "icmp"] -categories = ["command-line-utilities", "network-programming"] readme = "README.md" license = "Apache-2.0" edition = "2021" rust-version = "1.75" -exclude = ["assets/legacy", "assets/*/*.png"] - -[[bin]] -bench = false -path = "src/main.rs" -name = "trip" -[dependencies] - -# Library dependencies -arrayvec = { version = "0.7.4", default-features = false } -derive_more = { version = "0.99.17", default-features = false, features = [ "mul", "add", "add_assign" ] } -socket2 = { version = "0.5.7", default-features = false } +[workspace.dependencies] thiserror = "1.0.60" -tracing = { version = "0.1.40", default-features = false } - -# TUI dependencies anyhow = "1.0.83" -dns-lookup = "2.0.4" -hickory-resolver = "0.24.1" -crossbeam = "0.8.4" -clap = { version = "4.4.0", default-features = false, features = [ "cargo", "derive", "wrap_help", "usage", "unstable-styles" ] } -clap_complete = "4.4.9" -humantime = "2.1.0" -parking_lot = "0.12.2" -ratatui = "0.26.2" -crossterm = { version = "0.27.0", default-features = false, features = [ "events", "windows" ] } -chrono = { version = "0.4.38", default-features = false, features = [ "clock" ] } itertools = "0.12.1" serde = { version = "1.0.201", default-features = false } -serde_json = { version = "1.0.117", default-features = false } -comfy-table = { version = "7.1.0", default-features = false } -strum = { version = "0.26.2", default-features = false, features = [ "std", "derive" ] } -etcetera = "0.8.0" -toml = { version = "0.8.13", default-features = false, features = [ "parse" ] } -indexmap = { version = "2.2.6", default-features = false } -maxminddb = "0.24.0" -tracing-subscriber = { version = "0.3.18", default-features = false, features = [ "json", "env-filter" ] } -tracing-chrome = "0.7.2" -petgraph = "0.6.5" -csv = "1.3.0" -serde_with = "3.8.1" -encoding_rs_io = "0.1.7" -bitflags = "2.5.0" -clap_mangen = "0.2.20" - -# Library dependencies (Linux) -[target.'cfg(target_os = "linux")'.dependencies] -caps = "0.5.5" - -# Library dependencies (Unix) -[target.'cfg(unix)'.dependencies] -nix = { version = "0.28.0", default-features = false, features = [ "user", "poll", "net" ] } - -# Library dependencies (Windows) -[target.'cfg(windows)'.dependencies] -paste = "1.0.15" -widestring = "1.0.2" -windows-sys = { version = "0.52.0", features = [ - "Win32_Foundation", - "Win32_Networking_WinSock", - "Win32_System_IO", - "Win32_NetworkManagement_IpHelper", - "Win32_NetworkManagement_Ndis", - "Win32_System_IO", - "Win32_System_Threading", - "Win32_Security", -] } - -[dev-dependencies] -hex-literal = "0.4.1" -pretty_assertions = "1.4.0" -rand = "0.8.5" -test-case = "3.3.1" serde_yaml = "=0.9.33" -tokio = { version = "1.37.0", features = [ "full" ] } -tokio-util = "0.7.11" -ipnetwork = "0.20.0" -mockall = "0.12.1" - -# see https://github.com/meh/rust-tun/pull/74 -[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dev-dependencies] -tun2 = { version = "1.3.0", features = [ "async" ] } - -[features] -# Enable simulation integration tests -sim-tests = [] - -# cargo-generate-rpm dependencies -[package.metadata.generate-rpm] -assets = [ - { source = "target/release/trip", dest = "/usr/bin/trip", mode = "755" }, -] +tracing = { version = "0.1.40" } +derive_more = { version = "0.99.17", default-features = false, features = [ "mul", "add", "add_assign" ] } +test-case = "3.3.1" +parking_lot = "0.12.2" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d010bf8e..5f7420b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,32 @@ -FROM rust:1.74 as build-env +FROM rust:1.75 as build-env RUN rustup target add x86_64-unknown-linux-musl WORKDIR /app COPY Cargo.toml /app COPY Cargo.lock /app -RUN mkdir /app/src -RUN echo "fn main() {}" > /app/src/main.rs +RUN mkdir -p /app/crates/trippy/src +RUN mkdir -p /app/crates/trippy-core/src +RUN mkdir -p /app/crates/trippy-dns/src +RUN mkdir -p /app/crates/trippy-privilege/src +COPY crates/trippy/Cargo.toml /app/crates/trippy/Cargo.toml +COPY crates/trippy-core/Cargo.toml /app/crates/trippy-core/Cargo.toml +COPY crates/trippy-dns/Cargo.toml /app/crates/trippy-dns/Cargo.toml +COPY crates/trippy-privilege/Cargo.toml /app/crates/trippy-privilege/Cargo.toml + +# dummy build to cache dependencies +RUN echo "fn main() {}" > /app/crates/trippy/src/main.rs +RUN touch /app/crates/trippy-core/src/lib.rs +RUN touch /app/crates/trippy-dns/src/lib.rs +RUN touch /app/crates/trippy-privilege/src/lib.rs RUN cargo build --release --target=x86_64-unknown-linux-musl -COPY src /app/src + +# copy the actual application code and build +COPY crates/trippy/src /app/crates/trippy/src +COPY crates/trippy-core/src /app/crates/trippy-core/src +COPY crates/trippy-dns/src /app/crates/trippy-dns/src +COPY crates/trippy-privilege/src /app/crates/trippy-privilege/src COPY trippy-config-sample.toml /app COPY README.md /app -COPY LICENSE /app +RUN cargo clean --release --target=x86_64-unknown-linux-musl -p trippy-core -p trippy-dns -p trippy-privilege RUN cargo build --release --target=x86_64-unknown-linux-musl FROM alpine diff --git a/crates/README.md b/crates/README.md new file mode 100644 index 00000000..9cd8070d --- /dev/null +++ b/crates/README.md @@ -0,0 +1,39 @@ +## Crates + +The following is a list of the crates defined by Trippy and their purposes: + +### `trippy` + +A binary crate for the Trippy application. This is the crate you would use if you wish to install and run Trippy as a +standalone tool. + +```shell +cargo install --locked trippy +``` + +### `trippy-core` + +A library crate providing the core Trippy tracing functionality. This crate is used by the Trippy application and is +the crate you would use if you wish to provide the Trippy tracing functionality in your own application. + +```shell +cargo add trippy-core +``` + +### `trippy-dns` + +A library crate for performing forward and reverse lazy DNS resolution. This crate is designed to be used by the Trippy +application but may also be useful for other applications that need to perform forward and reverse lazy DNS resolution. + +```shell +cargo add trippy-dns +``` + +### `trippy-privilege` + +A library crate for discovering platform privileges. This crate is designed to be used by the Trippy application but +may also be useful for other applications. + +```shell +cargo add trippy-privilege +``` \ No newline at end of file diff --git a/crates/trippy-core/Cargo.toml b/crates/trippy-core/Cargo.toml new file mode 100644 index 00000000..754c4c20 --- /dev/null +++ b/crates/trippy-core/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "trippy-core" +description = "A network tracing library" +version.workspace = true +authors.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +keywords = ["traceroute", "ping", "icmp"] +categories = ["network-programming"] + +[dependencies] +derive_more.workspace = true +thiserror.workspace = true +tracing.workspace = true +itertools.workspace = true +arrayvec = { version = "0.7.4", default-features = false } +socket2 = { version = "0.5.7", features = [ "all" ] } +bitflags = "2.5.0" + +[target.'cfg(unix)'.dependencies] +nix = { version = "0.28.0", default-features = false, features = [ "user", "poll", "net" ] } + +[target.'cfg(windows)'.dependencies] +paste = "1.0.15" +widestring = "1.0.2" +windows-sys = { version = "0.52.0", features = [ + "Win32_Foundation", + "Win32_Networking_WinSock", + "Win32_System_IO", + "Win32_NetworkManagement_IpHelper", + "Win32_NetworkManagement_Ndis", + "Win32_System_IO", + "Win32_System_Threading", + "Win32_Security", +] } + +[dev-dependencies] +anyhow.workspace = true +serde.workspace = true +test-case.workspace = true +serde_yaml.workspace = true +hex-literal = "0.4.1" +rand = "0.8.5" +tokio = { version = "1.37.0", features = [ "full" ] } +tokio-util = "0.7.11" +ipnetwork = "0.20.0" +mockall = "0.12.1" +tracing-subscriber = "0.3.18" + +# see https://github.com/meh/rust-tun/pull/74 +[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dev-dependencies] +tun2 = { version = "1.3.0", features = [ "async" ] } + +[features] +# Enable simulation integration tests +sim-tests = [] \ No newline at end of file diff --git a/src/tracing/builder.rs b/crates/trippy-core/src/builder.rs similarity index 97% rename from src/tracing/builder.rs rename to crates/trippy-core/src/builder.rs index 3a563829..1e3a4e88 100644 --- a/src/tracing/builder.rs +++ b/crates/trippy-core/src/builder.rs @@ -1,6 +1,6 @@ -use crate::tracing::error::TraceResult; -use crate::tracing::net::PlatformImpl; -use crate::tracing::{ +use crate::error::TraceResult; +use crate::net::PlatformImpl; +use crate::{ ChannelConfig, Config, IcmpExtensionParseMode, MaxInflight, MaxRounds, MultipathStrategy, PacketSize, PayloadPattern, PortDirection, PrivilegeMode, Protocol, Sequence, SocketImpl, SourceAddr, TimeToLive, TraceId, Tracer, TracerChannel, TracerRound, TypeOfService, @@ -19,7 +19,7 @@ use std::time::Duration; /// # Examples: /// /// ```no_run -/// use trippy::tracing::{Builder, MultipathStrategy, Port, PortDirection, PrivilegeMode, Protocol}; +/// use trippy_core::{Builder, MultipathStrategy, Port, PortDirection, PrivilegeMode, Protocol}; /// /// let addr = std::net::IpAddr::from([1, 2, 3, 4]); /// Builder::new(addr, |round| println!("{:?}", round)) diff --git a/src/tracing/config.rs b/crates/trippy-core/src/config.rs similarity index 98% rename from src/tracing/config.rs rename to crates/trippy-core/src/config.rs index f92a4dff..44c8f718 100644 --- a/src/tracing/config.rs +++ b/crates/trippy-core/src/config.rs @@ -1,6 +1,6 @@ -use crate::tracing::constants::{MAX_INITIAL_SEQUENCE, MAX_TTL}; -use crate::tracing::error::{TraceResult, TracerError}; -use crate::tracing::types::{ +use crate::constants::{MAX_INITIAL_SEQUENCE, MAX_TTL}; +use crate::error::{TraceResult, TracerError}; +use crate::types::{ MaxInflight, MaxRounds, PacketSize, PayloadPattern, Port, Sequence, TimeToLive, TraceId, TypeOfService, }; @@ -9,9 +9,10 @@ use std::net::{IpAddr, Ipv4Addr}; use std::num::NonZeroUsize; use std::time::Duration; +/// Default values for configuration. pub mod defaults { - use crate::tracing::config::IcmpExtensionParseMode; - use crate::tracing::{MultipathStrategy, PrivilegeMode, Protocol}; + use crate::config::IcmpExtensionParseMode; + use crate::{MultipathStrategy, PrivilegeMode, Protocol}; use std::time::Duration; /// The default value for `unprivileged`. diff --git a/src/tracing/constants.rs b/crates/trippy-core/src/constants.rs similarity index 100% rename from src/tracing/constants.rs rename to crates/trippy-core/src/constants.rs diff --git a/src/tracing/error.rs b/crates/trippy-core/src/error.rs similarity index 98% rename from src/tracing/error.rs rename to crates/trippy-core/src/error.rs index 0b2cbfde..cc6e7400 100644 --- a/src/tracing/error.rs +++ b/crates/trippy-core/src/error.rs @@ -1,4 +1,4 @@ -use crate::tracing::packet::error::PacketError; +use crate::packet::error::PacketError; use std::fmt::{Display, Formatter}; use std::io; use std::io::ErrorKind; diff --git a/crates/trippy-core/src/lib.rs b/crates/trippy-core/src/lib.rs new file mode 100644 index 00000000..b27e2c22 --- /dev/null +++ b/crates/trippy-core/src/lib.rs @@ -0,0 +1,85 @@ +//! Trippy - A network tracing library. +//! +//! This crate provides the core network tracing facility used by the +//! standalone [Trippy](https://trippy.cli.rs) application. +//! +//! Note: the public API is not stable and is highly likely to change +//! in the future. +//! +//! # Example +//! +//! The following example builds and runs a tracer with default configuration +//! and prints out the tracing data for each round: +//! +//! ```no_run +//! # fn main() -> anyhow::Result<()> { +//! # use std::net::IpAddr; +//! # use std::str::FromStr; +//! use trippy_core::Builder; +//! +//! let addr = IpAddr::from_str("1.1.1.1")?; +//! Builder::new(addr, |round| println!("{:?}", round)).start()?; +//! # Ok(()) +//! # } +//! ``` +//! +//! The following example traces using the UDP protocol with the Dublin ECMP +//! strategy with fixed src and dest ports. It also operates in unprivileged +//! mode (only supported on some platforms): +//! +//! ```no_run +//! # fn main() -> anyhow::Result<()> { +//! # use std::net::IpAddr; +//! # use std::str::FromStr; +//! use trippy_core::{Builder, MultipathStrategy, Port, PortDirection, PrivilegeMode, Protocol}; +//! +//! let addr = IpAddr::from_str("1.1.1.1")?; +//! Builder::new(addr, |round| println!("{:?}", round)) +//! .privilege_mode(PrivilegeMode::Unprivileged) +//! .protocol(Protocol::Udp) +//! .multipath_strategy(MultipathStrategy::Dublin) +//! .port_direction(PortDirection::FixedBoth(Port(33000), Port(3500))) +//! .start()?; +//! # Ok(()) +//! # } +//! ``` +#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)] +#![allow( + clippy::module_name_repetitions, + clippy::struct_field_names, + clippy::option_if_let_else, + clippy::missing_const_for_fn, + clippy::cast_possible_truncation, + clippy::missing_errors_doc +)] +#![deny(unsafe_code)] + +mod builder; +mod config; +mod constants; +mod error; +mod net; +mod probe; +mod tracer; +mod types; + +/// Packet wire formats. +pub mod packet; + +pub use builder::Builder; +pub use config::{ + defaults, ChannelConfig, ChannelConfigBuilder, Config, ConfigBuilder, IcmpExtensionParseMode, + MultipathStrategy, PortDirection, PrivilegeMode, Protocol, +}; +pub use net::channel::TracerChannel; +pub use net::source::SourceAddr; +pub use net::{PlatformImpl, SocketImpl}; +pub use probe::{ + Extension, Extensions, IcmpPacketType, MplsLabelStack, MplsLabelStackMember, Probe, + ProbeComplete, ProbeState, UnknownExtension, +}; +pub use tracer::{CompletionReason, Tracer, TracerRound}; +pub use types::{ + Flags, MaxInflight, MaxRounds, PacketSize, PayloadPattern, Port, Round, Sequence, TimeToLive, + TraceId, TypeOfService, +}; diff --git a/src/tracing/net.rs b/crates/trippy-core/src/net.rs similarity index 90% rename from src/tracing/net.rs rename to crates/trippy-core/src/net.rs index 19cb3052..bbab0128 100644 --- a/src/tracing/net.rs +++ b/crates/trippy-core/src/net.rs @@ -1,5 +1,5 @@ -use crate::tracing::error::TraceResult; -use crate::tracing::probe::{Probe, ProbeResponse}; +use crate::error::TraceResult; +use crate::probe::{Probe, ProbeResponse}; /// Common types and helper functions. mod common; diff --git a/src/tracing/net/channel.rs b/crates/trippy-core/src/net/channel.rs similarity index 95% rename from src/tracing/net/channel.rs rename to crates/trippy-core/src/net/channel.rs index a08e49af..f6675f71 100644 --- a/src/tracing/net/channel.rs +++ b/crates/trippy-core/src/net/channel.rs @@ -1,10 +1,10 @@ -use crate::tracing::config::IcmpExtensionParseMode; -use crate::tracing::error::{TraceResult, TracerError}; -use crate::tracing::net::socket::Socket; -use crate::tracing::net::{ipv4, ipv6, platform, Network}; -use crate::tracing::probe::{Probe, ProbeResponse}; -use crate::tracing::types::{PacketSize, PayloadPattern, TypeOfService}; -use crate::tracing::{ChannelConfig, Port, PrivilegeMode, Protocol, Sequence}; +use crate::config::IcmpExtensionParseMode; +use crate::error::{TraceResult, TracerError}; +use crate::net::socket::Socket; +use crate::net::{ipv4, ipv6, platform, Network}; +use crate::probe::{Probe, ProbeResponse}; +use crate::types::{PacketSize, PayloadPattern, TypeOfService}; +use crate::{ChannelConfig, Port, PrivilegeMode, Protocol, Sequence}; use arrayvec::ArrayVec; use std::net::IpAddr; use std::time::{Duration, SystemTime}; diff --git a/src/tracing/net/common.rs b/crates/trippy-core/src/net/common.rs similarity index 92% rename from src/tracing/net/common.rs rename to crates/trippy-core/src/net/common.rs index 6405f768..ae3f9400 100644 --- a/src/tracing/net/common.rs +++ b/crates/trippy-core/src/net/common.rs @@ -1,5 +1,5 @@ -use crate::tracing::error::{IoResult, TraceResult, TracerError}; -use crate::tracing::net::platform::in_progress_error; +use crate::error::{IoResult, TraceResult, TracerError}; +use crate::net::platform::in_progress_error; use std::io::ErrorKind; use std::net::SocketAddr; @@ -25,9 +25,9 @@ pub fn process_result(addr: SocketAddr, res: IoResult<()>) -> TraceResult<()> { #[cfg(test)] mod tests { use super::*; - use crate::tracing::error::{IoError, IoOperation}; + use crate::error::{IoError, IoOperation}; + use std::io; use std::net::{Ipv4Addr, SocketAddrV4}; - use tokio::io; const ADDR: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)); diff --git a/src/tracing/net/extension.rs b/crates/trippy-core/src/net/extension.rs similarity index 87% rename from src/tracing/net/extension.rs rename to crates/trippy-core/src/net/extension.rs index cefdeea8..31485248 100644 --- a/src/tracing/net/extension.rs +++ b/crates/trippy-core/src/net/extension.rs @@ -1,12 +1,10 @@ -use crate::tracing::error::TracerError; -use crate::tracing::packet::icmp_extension::extension_header::ExtensionHeaderPacket; -use crate::tracing::packet::icmp_extension::extension_object::{ClassNum, ExtensionObjectPacket}; -use crate::tracing::packet::icmp_extension::extension_structure::ExtensionsPacket; -use crate::tracing::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; -use crate::tracing::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; -use crate::tracing::probe::{ - Extension, Extensions, MplsLabelStack, MplsLabelStackMember, UnknownExtension, -}; +use crate::error::TracerError; +use crate::packet::icmp_extension::extension_header::ExtensionHeaderPacket; +use crate::packet::icmp_extension::extension_object::{ClassNum, ExtensionObjectPacket}; +use crate::packet::icmp_extension::extension_structure::ExtensionsPacket; +use crate::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; +use crate::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; +use crate::probe::{Extension, Extensions, MplsLabelStack, MplsLabelStackMember, UnknownExtension}; /// The supported ICMP extension version number. const ICMP_EXTENSION_VERSION: u8 = 2; diff --git a/src/tracing/net/ipv4.rs b/crates/trippy-core/src/net/ipv4.rs similarity index 97% rename from src/tracing/net/ipv4.rs rename to crates/trippy-core/src/net/ipv4.rs index 239236b6..511a4a80 100644 --- a/src/tracing/net/ipv4.rs +++ b/crates/trippy-core/src/net/ipv4.rs @@ -1,25 +1,25 @@ -use crate::tracing::config::IcmpExtensionParseMode; -use crate::tracing::error::{TraceResult, TracerError}; -use crate::tracing::net::channel::MAX_PACKET_SIZE; -use crate::tracing::net::common::process_result; -use crate::tracing::net::platform; -use crate::tracing::net::socket::{Socket, SocketError}; -use crate::tracing::packet::checksum::{icmp_ipv4_checksum, udp_ipv4_checksum}; -use crate::tracing::packet::icmpv4::destination_unreachable::DestinationUnreachablePacket; -use crate::tracing::packet::icmpv4::echo_reply::EchoReplyPacket; -use crate::tracing::packet::icmpv4::echo_request::EchoRequestPacket; -use crate::tracing::packet::icmpv4::time_exceeded::TimeExceededPacket; -use crate::tracing::packet::icmpv4::{IcmpCode, IcmpPacket, IcmpTimeExceededCode, IcmpType}; -use crate::tracing::packet::ipv4::Ipv4Packet; -use crate::tracing::packet::tcp::TcpPacket; -use crate::tracing::packet::udp::UdpPacket; -use crate::tracing::packet::IpProtocol; -use crate::tracing::probe::{ +use crate::config::IcmpExtensionParseMode; +use crate::error::{TraceResult, TracerError}; +use crate::net::channel::MAX_PACKET_SIZE; +use crate::net::common::process_result; +use crate::net::platform; +use crate::net::socket::{Socket, SocketError}; +use crate::packet::checksum::{icmp_ipv4_checksum, udp_ipv4_checksum}; +use crate::packet::icmpv4::destination_unreachable::DestinationUnreachablePacket; +use crate::packet::icmpv4::echo_reply::EchoReplyPacket; +use crate::packet::icmpv4::echo_request::EchoRequestPacket; +use crate::packet::icmpv4::time_exceeded::TimeExceededPacket; +use crate::packet::icmpv4::{IcmpCode, IcmpPacket, IcmpTimeExceededCode, IcmpType}; +use crate::packet::ipv4::Ipv4Packet; +use crate::packet::tcp::TcpPacket; +use crate::packet::udp::UdpPacket; +use crate::packet::IpProtocol; +use crate::probe::{ Extensions, IcmpPacketCode, Probe, ProbeResponse, ProbeResponseData, ProbeResponseSeq, ProbeResponseSeqIcmp, ProbeResponseSeqTcp, ProbeResponseSeqUdp, }; -use crate::tracing::types::{PacketSize, PayloadPattern, Sequence, TraceId, TypeOfService}; -use crate::tracing::{Flags, Port, PrivilegeMode, Protocol}; +use crate::types::{PacketSize, PayloadPattern, Sequence, TraceId, TypeOfService}; +use crate::{Flags, Port, PrivilegeMode, Protocol}; use std::io::ErrorKind; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::time::SystemTime; @@ -504,10 +504,10 @@ fn extract_tcp_packet(ipv4: &Ipv4Packet<'_>) -> TraceResult<(u16, u16)> { #[cfg(test)] mod tests { use super::*; + use crate::error::IoResult; use crate::mocket_read; - use crate::tracing::error::IoResult; - use crate::tracing::net::socket::MockSocket; - use crate::tracing::{Flags, Port, Round, TimeToLive}; + use crate::net::socket::MockSocket; + use crate::{Flags, Port, Round, TimeToLive}; use mockall::predicate; use std::str::FromStr; use std::sync::Mutex; diff --git a/src/tracing/net/ipv6.rs b/crates/trippy-core/src/net/ipv6.rs similarity index 98% rename from src/tracing/net/ipv6.rs rename to crates/trippy-core/src/net/ipv6.rs index d411dffe..92a788a6 100644 --- a/src/tracing/net/ipv6.rs +++ b/crates/trippy-core/src/net/ipv6.rs @@ -1,24 +1,24 @@ -use crate::tracing::config::IcmpExtensionParseMode; -use crate::tracing::error::{TraceResult, TracerError}; -use crate::tracing::net::channel::MAX_PACKET_SIZE; -use crate::tracing::net::common::process_result; -use crate::tracing::net::socket::{Socket, SocketError}; -use crate::tracing::packet::checksum::{icmp_ipv6_checksum, udp_ipv6_checksum}; -use crate::tracing::packet::icmpv6::destination_unreachable::DestinationUnreachablePacket; -use crate::tracing::packet::icmpv6::echo_reply::EchoReplyPacket; -use crate::tracing::packet::icmpv6::echo_request::EchoRequestPacket; -use crate::tracing::packet::icmpv6::time_exceeded::TimeExceededPacket; -use crate::tracing::packet::icmpv6::{IcmpCode, IcmpPacket, IcmpTimeExceededCode, IcmpType}; -use crate::tracing::packet::ipv6::Ipv6Packet; -use crate::tracing::packet::tcp::TcpPacket; -use crate::tracing::packet::udp::UdpPacket; -use crate::tracing::packet::IpProtocol; -use crate::tracing::probe::{ +use crate::config::IcmpExtensionParseMode; +use crate::error::{TraceResult, TracerError}; +use crate::net::channel::MAX_PACKET_SIZE; +use crate::net::common::process_result; +use crate::net::socket::{Socket, SocketError}; +use crate::packet::checksum::{icmp_ipv6_checksum, udp_ipv6_checksum}; +use crate::packet::icmpv6::destination_unreachable::DestinationUnreachablePacket; +use crate::packet::icmpv6::echo_reply::EchoReplyPacket; +use crate::packet::icmpv6::echo_request::EchoRequestPacket; +use crate::packet::icmpv6::time_exceeded::TimeExceededPacket; +use crate::packet::icmpv6::{IcmpCode, IcmpPacket, IcmpTimeExceededCode, IcmpType}; +use crate::packet::ipv6::Ipv6Packet; +use crate::packet::tcp::TcpPacket; +use crate::packet::udp::UdpPacket; +use crate::packet::IpProtocol; +use crate::probe::{ Extensions, IcmpPacketCode, Probe, ProbeResponse, ProbeResponseData, ProbeResponseSeq, ProbeResponseSeqIcmp, ProbeResponseSeqTcp, ProbeResponseSeqUdp, }; -use crate::tracing::types::{PacketSize, PayloadPattern, Sequence, TraceId}; -use crate::tracing::{Flags, Port, PrivilegeMode, Protocol}; +use crate::types::{PacketSize, PayloadPattern, Sequence, TraceId}; +use crate::{Flags, Port, PrivilegeMode, Protocol}; use std::io::ErrorKind; use std::net::{IpAddr, Ipv6Addr, SocketAddr}; use std::time::SystemTime; @@ -472,10 +472,10 @@ fn udp_payload_has_magic_prefix(ipv6: &Ipv6Packet<'_>) -> TraceResult { #[cfg(test)] mod tests { use super::*; + use crate::error::IoResult; use crate::mocket_recv_from; - use crate::tracing::error::IoResult; - use crate::tracing::net::socket::MockSocket; - use crate::tracing::{Flags, Port, Round, TimeToLive}; + use crate::net::socket::MockSocket; + use crate::{Flags, Port, Round, TimeToLive}; use mockall::predicate; use std::str::FromStr; use std::sync::Mutex; diff --git a/src/tracing/net/platform.rs b/crates/trippy-core/src/net/platform.rs similarity index 95% rename from src/tracing/net/platform.rs rename to crates/trippy-core/src/net/platform.rs index 7050d246..8fc74cda 100644 --- a/src/tracing/net/platform.rs +++ b/crates/trippy-core/src/net/platform.rs @@ -6,7 +6,7 @@ use std::net::IpAddr; #[cfg(unix)] mod unix; -use crate::tracing::error::TraceResult; +use crate::error::TraceResult; #[cfg(unix)] pub use unix::*; diff --git a/src/tracing/net/platform/byte_order.rs b/crates/trippy-core/src/net/platform/byte_order.rs similarity index 96% rename from src/tracing/net/platform/byte_order.rs rename to crates/trippy-core/src/net/platform/byte_order.rs index 75a43e6d..88fa0cef 100644 --- a/src/tracing/net/platform/byte_order.rs +++ b/crates/trippy-core/src/net/platform/byte_order.rs @@ -1,5 +1,5 @@ -use crate::tracing::error::TraceResult; -use crate::tracing::net::platform::{Platform, PlatformImpl}; +use crate::error::TraceResult; +use crate::net::platform::{Platform, PlatformImpl}; use std::net::IpAddr; /// The byte order to encode the `total_length`, `flags` and `fragment_offset` fields of the IPv4 diff --git a/src/tracing/net/platform/unix.rs b/crates/trippy-core/src/net/platform/unix.rs similarity index 97% rename from src/tracing/net/platform/unix.rs rename to crates/trippy-core/src/net/platform/unix.rs index 9d639b70..5352648f 100644 --- a/src/tracing/net/platform/unix.rs +++ b/crates/trippy-core/src/net/platform/unix.rs @@ -1,5 +1,5 @@ -use crate::tracing::error::TraceResult; -use crate::tracing::net::platform::{Ipv4ByteOrder, Platform}; +use crate::error::TraceResult; +use crate::net::platform::{Ipv4ByteOrder, Platform}; use std::net::IpAddr; pub struct PlatformImpl; @@ -17,10 +17,10 @@ impl Platform for PlatformImpl { } mod address { - use crate::tracing::error::{TraceResult, TracerError}; - use crate::tracing::net::platform::Ipv4ByteOrder; - use crate::tracing::net::socket::Socket; - use crate::tracing::SocketImpl; + use crate::error::{TraceResult, TracerError}; + use crate::net::platform::Ipv4ByteOrder; + use crate::net::socket::Socket; + use crate::SocketImpl; use nix::sys::socket::{AddressFamily, SockaddrLike}; use std::net::{IpAddr, SocketAddr}; use tracing::instrument; @@ -72,7 +72,7 @@ mod address { #[cfg(not(target_os = "linux"))] #[instrument(ret)] fn test_send_local_ip4_packet(src_addr: Ipv4Addr, total_length: u16) -> TraceResult<()> { - use crate::tracing::packet; + use crate::packet; use socket2::Protocol; let mut icmp_buf = [0_u8; packet::icmpv4::IcmpPacket::minimum_packet_size()]; let mut icmp = packet::icmpv4::echo_request::EchoRequestPacket::new(&mut icmp_buf)?; @@ -149,9 +149,9 @@ mod address { } mod socket { - use crate::tracing::error::{IoError, IoOperation}; - use crate::tracing::error::{IoResult, TraceResult}; - use crate::tracing::net::socket::{Socket, SocketError}; + use crate::error::{IoError, IoOperation}; + use crate::error::{IoResult, TraceResult}; + use crate::net::socket::{Socket, SocketError}; use itertools::Itertools; use nix::{ sys::select::FdSet, diff --git a/src/tracing/net/platform/windows.rs b/crates/trippy-core/src/net/platform/windows.rs similarity index 98% rename from src/tracing/net/platform/windows.rs rename to crates/trippy-core/src/net/platform/windows.rs index bf3d1a31..c7436c0f 100644 --- a/src/tracing/net/platform/windows.rs +++ b/crates/trippy-core/src/net/platform/windows.rs @@ -1,9 +1,9 @@ use super::byte_order::Ipv4ByteOrder; -use crate::tracing::error::{IoError, IoOperation, IoResult, TraceResult, TracerError}; -use crate::tracing::net::channel::MAX_PACKET_SIZE; -use crate::tracing::net::platform::windows::adapter::Adapters; -use crate::tracing::net::platform::Platform; -use crate::tracing::net::socket::{Socket, SocketError}; +use crate::error::{IoError, IoOperation, IoResult, TraceResult, TracerError}; +use crate::net::channel::MAX_PACKET_SIZE; +use crate::net::platform::windows::adapter::Adapters; +use crate::net::platform::Platform; +use crate::net::socket::{Socket, SocketError}; use itertools::Itertools; use socket2::{Domain, Protocol, SockAddr, Type}; use std::ffi::c_void; @@ -735,8 +735,8 @@ fn lookup_interface_addr(adapters: &Adapters, name: &str) -> TraceResult } mod adapter { - use crate::tracing::error::{TraceResult, TracerError}; - use crate::tracing::net::platform::windows::sockaddrptr_to_ipaddr; + use crate::error::{TraceResult, TracerError}; + use crate::net::platform::windows::sockaddrptr_to_ipaddr; use std::io::Error; use std::marker::PhantomData; use std::net::IpAddr; diff --git a/src/tracing/net/socket.rs b/crates/trippy-core/src/net/socket.rs similarity index 98% rename from src/tracing/net/socket.rs rename to crates/trippy-core/src/net/socket.rs index 4d5f6148..b3d381d4 100644 --- a/src/tracing/net/socket.rs +++ b/crates/trippy-core/src/net/socket.rs @@ -1,4 +1,4 @@ -use crate::tracing::error::IoResult as Result; +use crate::error::IoResult as Result; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::time::Duration; diff --git a/src/tracing/net/source.rs b/crates/trippy-core/src/net/source.rs similarity index 94% rename from src/tracing/net/source.rs rename to crates/trippy-core/src/net/source.rs index 3322ac87..fe9d3b67 100644 --- a/src/tracing/net/source.rs +++ b/crates/trippy-core/src/net/source.rs @@ -1,9 +1,9 @@ -use crate::tracing::error::TraceResult; -use crate::tracing::error::TracerError::InvalidSourceAddr; -use crate::tracing::net::platform::Platform; -use crate::tracing::net::socket::Socket; -use crate::tracing::types::Port; -use crate::tracing::PortDirection; +use crate::error::TraceResult; +use crate::error::TracerError::InvalidSourceAddr; +use crate::net::platform::Platform; +use crate::net::socket::Socket; +use crate::types::Port; +use crate::PortDirection; use std::net::{IpAddr, SocketAddr}; /// The port used for local address discovery if not dest port is available. @@ -46,9 +46,9 @@ impl SourceAddr { #[cfg(test)] mod tests { use super::*; - use crate::tracing::error::{IoError, TracerError}; - use crate::tracing::net::platform::MockPlatform; - use crate::tracing::net::socket::MockSocket; + use crate::error::{IoError, TracerError}; + use crate::net::platform::MockPlatform; + use crate::net::socket::MockSocket; use mockall::predicate; use std::io::Error; use std::str::FromStr; diff --git a/src/tracing/packet.rs b/crates/trippy-core/src/packet.rs similarity index 100% rename from src/tracing/packet.rs rename to crates/trippy-core/src/packet.rs diff --git a/src/tracing/packet/buffer.rs b/crates/trippy-core/src/packet/buffer.rs similarity index 100% rename from src/tracing/packet/buffer.rs rename to crates/trippy-core/src/packet/buffer.rs diff --git a/src/tracing/packet/checksum.rs b/crates/trippy-core/src/packet/checksum.rs similarity index 99% rename from src/tracing/packet/checksum.rs rename to crates/trippy-core/src/packet/checksum.rs index 40cca291..be99fdca 100644 --- a/src/tracing/packet/checksum.rs +++ b/crates/trippy-core/src/packet/checksum.rs @@ -4,7 +4,7 @@ //! //! [`libpnet`]: https://github.com/libpnet/libpnet -use crate::tracing::packet::IpProtocol; +use crate::packet::IpProtocol; use std::net::{Ipv4Addr, Ipv6Addr}; /// Calculate the checksum for an `Ipv4` header. diff --git a/src/tracing/packet/error.rs b/crates/trippy-core/src/packet/error.rs similarity index 100% rename from src/tracing/packet/error.rs rename to crates/trippy-core/src/packet/error.rs diff --git a/src/tracing/packet/icmp_extension.rs b/crates/trippy-core/src/packet/icmp_extension.rs similarity index 95% rename from src/tracing/packet/icmp_extension.rs rename to crates/trippy-core/src/packet/icmp_extension.rs index 148de7ab..69f39a18 100644 --- a/src/tracing/packet/icmp_extension.rs +++ b/crates/trippy-core/src/packet/icmp_extension.rs @@ -1,7 +1,7 @@ pub mod extension_structure { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::icmp_extension::extension_object::ExtensionObjectPacket; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::icmp_extension::extension_object::ExtensionObjectPacket; /// Represents an ICMP `ExtensionsPacket` pseudo object. /// @@ -104,8 +104,8 @@ pub mod extension_structure { #[cfg(test)] mod tests { use super::*; - use crate::tracing::packet::icmp_extension::extension_header::ExtensionHeaderPacket; - use crate::tracing::packet::icmp_extension::extension_object::{ + use crate::packet::icmp_extension::extension_header::ExtensionHeaderPacket; + use crate::packet::icmp_extension::extension_object::{ ClassNum, ClassSubType, ExtensionObjectPacket, }; @@ -152,8 +152,8 @@ pub mod extension_structure { } pub mod extension_header { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; use std::fmt::{Debug, Formatter}; const VERSION_OFFSET: usize = 0; @@ -286,9 +286,9 @@ pub mod extension_header { } pub mod extension_object { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; use std::fmt::{Debug, Formatter}; /// The ICMP Extension Object Class Num. @@ -518,9 +518,9 @@ pub mod extension_object { } pub mod mpls_label_stack { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; /// Represents an ICMP `MplsLabelStackPacket`. /// @@ -633,8 +633,8 @@ pub mod mpls_label_stack { } pub mod mpls_label_stack_member { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; use std::fmt::{Debug, Formatter}; const LABEL_OFFSET: usize = 0; @@ -842,7 +842,7 @@ pub mod mpls_label_stack_member { } pub mod extension_splitter { - use crate::tracing::packet::icmp_extension::extension_header::ExtensionHeaderPacket; + use crate::packet::icmp_extension::extension_header::ExtensionHeaderPacket; const MIN_HEADER: usize = ExtensionHeaderPacket::minimum_packet_size(); /// From rfc4884 (section 3) entitled "Summary of Changes to ICMP": @@ -898,13 +898,13 @@ pub mod extension_splitter { #[cfg(test)] mod tests { use super::*; - use crate::tracing::packet::icmp_extension::extension_header::ExtensionHeaderPacket; - use crate::tracing::packet::icmp_extension::extension_object::{ + use crate::packet::icmp_extension::extension_header::ExtensionHeaderPacket; + use crate::packet::icmp_extension::extension_object::{ ClassNum, ClassSubType, ExtensionObjectPacket, }; - use crate::tracing::packet::icmp_extension::extension_structure::ExtensionsPacket; - use crate::tracing::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; - use crate::tracing::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; + use crate::packet::icmp_extension::extension_structure::ExtensionsPacket; + use crate::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; + use crate::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; #[test] fn test_split_empty_payload() { @@ -959,10 +959,10 @@ pub mod extension_splitter { mod ipv4 { use super::*; - use crate::tracing::packet::icmpv4::echo_request::EchoRequestPacket; - use crate::tracing::packet::icmpv4::time_exceeded::TimeExceededPacket; - use crate::tracing::packet::icmpv4::{IcmpCode, IcmpType}; - use crate::tracing::packet::ipv4::Ipv4Packet; + use crate::packet::icmpv4::echo_request::EchoRequestPacket; + use crate::packet::icmpv4::time_exceeded::TimeExceededPacket; + use crate::packet::icmpv4::{IcmpCode, IcmpType}; + use crate::packet::ipv4::Ipv4Packet; use std::net::Ipv4Addr; // This ICMP TimeExceeded packet which contains single `MPLS` extension @@ -1136,17 +1136,17 @@ pub mod extension_splitter { } mod ipv6 { - use crate::tracing::packet::icmp_extension::extension_header::ExtensionHeaderPacket; - use crate::tracing::packet::icmp_extension::extension_object::{ + use crate::packet::icmp_extension::extension_header::ExtensionHeaderPacket; + use crate::packet::icmp_extension::extension_object::{ ClassNum, ClassSubType, ExtensionObjectPacket, }; - use crate::tracing::packet::icmp_extension::extension_structure::ExtensionsPacket; - use crate::tracing::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; - use crate::tracing::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; - use crate::tracing::packet::icmpv6::echo_request::EchoRequestPacket; - use crate::tracing::packet::icmpv6::time_exceeded::TimeExceededPacket; - use crate::tracing::packet::icmpv6::{IcmpCode, IcmpType}; - use crate::tracing::packet::ipv6::Ipv6Packet; + use crate::packet::icmp_extension::extension_structure::ExtensionsPacket; + use crate::packet::icmp_extension::mpls_label_stack::MplsLabelStackPacket; + use crate::packet::icmp_extension::mpls_label_stack_member::MplsLabelStackMemberPacket; + use crate::packet::icmpv6::echo_request::EchoRequestPacket; + use crate::packet::icmpv6::time_exceeded::TimeExceededPacket; + use crate::packet::icmpv6::{IcmpCode, IcmpType}; + use crate::packet::ipv6::Ipv6Packet; // Real IPv6 example with an rfc4884 length of 10 (10 * 8 = 80 // octets). diff --git a/src/tracing/packet/icmpv4.rs b/crates/trippy-core/src/packet/icmpv4.rs similarity index 97% rename from src/tracing/packet/icmpv4.rs rename to crates/trippy-core/src/packet/icmpv4.rs index 1c1fd37f..4d766a53 100644 --- a/src/tracing/packet/icmpv4.rs +++ b/crates/trippy-core/src/packet/icmpv4.rs @@ -1,5 +1,5 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; use std::fmt::{Debug, Formatter}; /// The type of ICMP packet. @@ -236,10 +236,10 @@ mod tests { } pub mod echo_request { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmpv4::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmpv4::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -496,10 +496,10 @@ pub mod echo_request { } pub mod echo_reply { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmpv4::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmpv4::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -756,11 +756,11 @@ pub mod echo_reply { } pub mod time_exceeded { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmp_extension::extension_splitter::split; - use crate::tracing::packet::icmpv4::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmp_extension::extension_splitter::split; + use crate::packet::icmpv4::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -1011,11 +1011,11 @@ pub mod time_exceeded { } pub mod destination_unreachable { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmp_extension::extension_splitter::split; - use crate::tracing::packet::icmpv4::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmp_extension::extension_splitter::split; + use crate::packet::icmpv4::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; diff --git a/src/tracing/packet/icmpv6.rs b/crates/trippy-core/src/packet/icmpv6.rs similarity index 97% rename from src/tracing/packet/icmpv6.rs rename to crates/trippy-core/src/packet/icmpv6.rs index 2ec00bfe..70feb23e 100644 --- a/src/tracing/packet/icmpv6.rs +++ b/crates/trippy-core/src/packet/icmpv6.rs @@ -1,5 +1,5 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; use std::fmt::{Debug, Formatter}; /// The type of `ICMPv6` packet. @@ -236,10 +236,10 @@ mod tests { } pub mod echo_request { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmpv6::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmpv6::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -496,10 +496,10 @@ pub mod echo_request { } pub mod echo_reply { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmpv6::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmpv6::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -756,11 +756,11 @@ pub mod echo_reply { } pub mod time_exceeded { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmp_extension::extension_splitter::split; - use crate::tracing::packet::icmpv6::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmp_extension::extension_splitter::split; + use crate::packet::icmpv6::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; @@ -1008,11 +1008,11 @@ pub mod time_exceeded { } pub mod destination_unreachable { - use crate::tracing::packet::buffer::Buffer; - use crate::tracing::packet::error::{PacketError, PacketResult}; - use crate::tracing::packet::fmt_payload; - use crate::tracing::packet::icmp_extension::extension_splitter::split; - use crate::tracing::packet::icmpv6::{IcmpCode, IcmpType}; + use crate::packet::buffer::Buffer; + use crate::packet::error::{PacketError, PacketResult}; + use crate::packet::fmt_payload; + use crate::packet::icmp_extension::extension_splitter::split; + use crate::packet::icmpv6::{IcmpCode, IcmpType}; use std::fmt::{Debug, Formatter}; const TYPE_OFFSET: usize = 0; diff --git a/src/tracing/packet/ipv4.rs b/crates/trippy-core/src/packet/ipv4.rs similarity index 99% rename from src/tracing/packet/ipv4.rs rename to crates/trippy-core/src/packet/ipv4.rs index 34b2e573..223f902b 100644 --- a/src/tracing/packet/ipv4.rs +++ b/crates/trippy-core/src/packet/ipv4.rs @@ -1,6 +1,6 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; -use crate::tracing::packet::{fmt_payload, IpProtocol}; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; +use crate::packet::{fmt_payload, IpProtocol}; use std::fmt::{Debug, Formatter}; use std::net::Ipv4Addr; diff --git a/src/tracing/packet/ipv6.rs b/crates/trippy-core/src/packet/ipv6.rs similarity index 98% rename from src/tracing/packet/ipv6.rs rename to crates/trippy-core/src/packet/ipv6.rs index 7b48350d..337b9815 100644 --- a/src/tracing/packet/ipv6.rs +++ b/crates/trippy-core/src/packet/ipv6.rs @@ -1,6 +1,6 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; -use crate::tracing::packet::{fmt_payload, IpProtocol}; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; +use crate::packet::{fmt_payload, IpProtocol}; use std::fmt::{Debug, Formatter}; use std::net::Ipv6Addr; diff --git a/src/tracing/packet/tcp.rs b/crates/trippy-core/src/packet/tcp.rs similarity index 99% rename from src/tracing/packet/tcp.rs rename to crates/trippy-core/src/packet/tcp.rs index f2d5f49a..48d723bd 100644 --- a/src/tracing/packet/tcp.rs +++ b/crates/trippy-core/src/packet/tcp.rs @@ -1,6 +1,6 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; -use crate::tracing::packet::fmt_payload; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; +use crate::packet::fmt_payload; use std::fmt::{Debug, Formatter}; const SOURCE_PORT_OFFSET: usize = 0; diff --git a/src/tracing/packet/udp.rs b/crates/trippy-core/src/packet/udp.rs similarity index 98% rename from src/tracing/packet/udp.rs rename to crates/trippy-core/src/packet/udp.rs index 86d7e22d..187ad9f8 100644 --- a/src/tracing/packet/udp.rs +++ b/crates/trippy-core/src/packet/udp.rs @@ -1,6 +1,6 @@ -use crate::tracing::packet::buffer::Buffer; -use crate::tracing::packet::error::{PacketError, PacketResult}; -use crate::tracing::packet::fmt_payload; +use crate::packet::buffer::Buffer; +use crate::packet::error::{PacketError, PacketResult}; +use crate::packet::fmt_payload; use std::fmt::{Debug, Formatter}; const SOURCE_PORT_OFFSET: usize = 0; diff --git a/src/tracing/probe.rs b/crates/trippy-core/src/probe.rs similarity index 99% rename from src/tracing/probe.rs rename to crates/trippy-core/src/probe.rs index c406e2b8..d69d1b01 100644 --- a/src/tracing/probe.rs +++ b/crates/trippy-core/src/probe.rs @@ -1,4 +1,4 @@ -use crate::tracing::types::{Flags, Port, Round, Sequence, TimeToLive, TraceId}; +use crate::types::{Flags, Port, Round, Sequence, TimeToLive, TraceId}; use std::net::IpAddr; use std::time::SystemTime; diff --git a/src/tracing/tracer.rs b/crates/trippy-core/src/tracer.rs similarity index 98% rename from src/tracing/tracer.rs rename to crates/trippy-core/src/tracer.rs index 2ee688eb..2d664392 100644 --- a/src/tracing/tracer.rs +++ b/crates/trippy-core/src/tracer.rs @@ -1,13 +1,13 @@ use self::state::TracerState; -use crate::tracing::error::{TraceResult, TracerError}; -use crate::tracing::net::Network; -use crate::tracing::probe::{ +use crate::error::{TraceResult, TracerError}; +use crate::net::Network; +use crate::probe::{ ProbeResponse, ProbeResponseData, ProbeResponseSeq, ProbeResponseSeqIcmp, ProbeResponseSeqTcp, ProbeResponseSeqUdp, ProbeState, }; -use crate::tracing::types::{Sequence, TimeToLive, TraceId}; -use crate::tracing::Config; -use crate::tracing::{MultipathStrategy, PortDirection, Protocol}; +use crate::types::{Sequence, TimeToLive, TraceId}; +use crate::Config; +use crate::{MultipathStrategy, PortDirection, Protocol}; use std::net::IpAddr; use std::time::{Duration, SystemTime}; use tracing::instrument; @@ -345,9 +345,9 @@ impl)> Tracer { #[cfg(test)] mod tests { use super::*; - use crate::tracing::net::MockNetwork; - use crate::tracing::probe::IcmpPacketCode; - use crate::tracing::{MaxRounds, Port}; + use crate::net::MockNetwork; + use crate::probe::IcmpPacketCode; + use crate::{MaxRounds, Port}; use std::net::Ipv4Addr; use std::num::NonZeroUsize; @@ -416,10 +416,10 @@ mod tests { /// This is contained within a submodule to ensure that mutations are only performed via methods on /// the `TracerState` struct. mod state { - use crate::tracing::constants::MAX_SEQUENCE_PER_ROUND; - use crate::tracing::probe::{Extensions, IcmpPacketCode, IcmpPacketType, Probe, ProbeState}; - use crate::tracing::types::{MaxRounds, Port, Round, Sequence, TimeToLive, TraceId}; - use crate::tracing::{Config, Flags, MultipathStrategy, PortDirection, Protocol}; + use crate::constants::MAX_SEQUENCE_PER_ROUND; + use crate::probe::{Extensions, IcmpPacketCode, IcmpPacketType, Probe, ProbeState}; + use crate::types::{MaxRounds, Port, Round, Sequence, TimeToLive, TraceId}; + use crate::{Config, Flags, MultipathStrategy, PortDirection, Protocol}; use std::array::from_fn; use std::net::IpAddr; use std::time::SystemTime; @@ -907,8 +907,8 @@ mod state { #[cfg(test)] mod tests { use super::*; - use crate::tracing::probe::IcmpPacketType; - use crate::tracing::types::MaxInflight; + use crate::probe::IcmpPacketType; + use crate::types::MaxInflight; use rand::Rng; use std::net::{IpAddr, Ipv4Addr}; use std::time::Duration; diff --git a/src/tracing/types.rs b/crates/trippy-core/src/types.rs similarity index 100% rename from src/tracing/types.rs rename to crates/trippy-core/src/types.rs diff --git a/tests/resources/simulation/ipv4_icmp.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp.yaml diff --git a/tests/resources/simulation/ipv4_icmp_gaps.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_gaps.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_gaps.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_gaps.yaml diff --git a/tests/resources/simulation/ipv4_icmp_min.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_min.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_min.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_min.yaml diff --git a/tests/resources/simulation/ipv4_icmp_ooo.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_ooo.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_ooo.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_ooo.yaml diff --git a/tests/resources/simulation/ipv4_icmp_pattern.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_pattern.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_pattern.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_pattern.yaml diff --git a/tests/resources/simulation/ipv4_icmp_quick.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_quick.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_quick.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_quick.yaml diff --git a/tests/resources/simulation/ipv4_icmp_wrap.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_icmp_wrap.yaml similarity index 100% rename from tests/resources/simulation/ipv4_icmp_wrap.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_icmp_wrap.yaml diff --git a/tests/resources/simulation/ipv4_tcp_fixed_dest.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_tcp_fixed_dest.yaml similarity index 100% rename from tests/resources/simulation/ipv4_tcp_fixed_dest.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_tcp_fixed_dest.yaml diff --git a/tests/resources/simulation/ipv4_udp_classic_fixed_dest.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_fixed_dest.yaml similarity index 100% rename from tests/resources/simulation/ipv4_udp_classic_fixed_dest.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_fixed_dest.yaml diff --git a/tests/resources/simulation/ipv4_udp_classic_fixed_src.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_fixed_src.yaml similarity index 100% rename from tests/resources/simulation/ipv4_udp_classic_fixed_src.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_fixed_src.yaml diff --git a/tests/resources/simulation/ipv4_udp_classic_unprivileged.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_unprivileged.yaml similarity index 100% rename from tests/resources/simulation/ipv4_udp_classic_unprivileged.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_udp_classic_unprivileged.yaml diff --git a/tests/resources/simulation/ipv4_udp_dublin_fixed_both.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_udp_dublin_fixed_both.yaml similarity index 100% rename from tests/resources/simulation/ipv4_udp_dublin_fixed_both.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_udp_dublin_fixed_both.yaml diff --git a/tests/resources/simulation/ipv4_udp_paris_fixed_both.yaml b/crates/trippy-core/tests/resources/simulation/ipv4_udp_paris_fixed_both.yaml similarity index 100% rename from tests/resources/simulation/ipv4_udp_paris_fixed_both.yaml rename to crates/trippy-core/tests/resources/simulation/ipv4_udp_paris_fixed_both.yaml diff --git a/tests/resources/wintun.dll b/crates/trippy-core/tests/resources/wintun.dll similarity index 100% rename from tests/resources/wintun.dll rename to crates/trippy-core/tests/resources/wintun.dll diff --git a/tests/sim/main.rs b/crates/trippy-core/tests/sim/main.rs similarity index 100% rename from tests/sim/main.rs rename to crates/trippy-core/tests/sim/main.rs diff --git a/tests/sim/network.rs b/crates/trippy-core/tests/sim/network.rs similarity index 94% rename from tests/sim/network.rs rename to crates/trippy-core/tests/sim/network.rs index 09e78798..2624670f 100644 --- a/tests/sim/network.rs +++ b/crates/trippy-core/tests/sim/network.rs @@ -8,18 +8,16 @@ use tokio::sync::Mutex; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; use tracing::{debug, info}; -use trippy::tracing::packet::checksum::{ - icmp_ipv4_checksum, ipv4_header_checksum, tcp_ipv4_checksum, -}; -use trippy::tracing::packet::icmpv4::destination_unreachable::DestinationUnreachablePacket; -use trippy::tracing::packet::icmpv4::echo_reply::EchoReplyPacket; -use trippy::tracing::packet::icmpv4::echo_request::EchoRequestPacket; -use trippy::tracing::packet::icmpv4::time_exceeded::TimeExceededPacket; -use trippy::tracing::packet::icmpv4::{IcmpCode, IcmpType}; -use trippy::tracing::packet::ipv4::Ipv4Packet; -use trippy::tracing::packet::tcp::TcpPacket; -use trippy::tracing::packet::udp::UdpPacket; -use trippy::tracing::packet::IpProtocol; +use trippy_core::packet::checksum::{icmp_ipv4_checksum, ipv4_header_checksum, tcp_ipv4_checksum}; +use trippy_core::packet::icmpv4::destination_unreachable::DestinationUnreachablePacket; +use trippy_core::packet::icmpv4::echo_reply::EchoReplyPacket; +use trippy_core::packet::icmpv4::echo_request::EchoRequestPacket; +use trippy_core::packet::icmpv4::time_exceeded::TimeExceededPacket; +use trippy_core::packet::icmpv4::{IcmpCode, IcmpType}; +use trippy_core::packet::ipv4::Ipv4Packet; +use trippy_core::packet::tcp::TcpPacket; +use trippy_core::packet::udp::UdpPacket; +use trippy_core::packet::IpProtocol; const READ_TIMEOUT: Duration = Duration::from_millis(10); diff --git a/tests/sim/simulation.rs b/crates/trippy-core/tests/sim/simulation.rs similarity index 92% rename from tests/sim/simulation.rs rename to crates/trippy-core/tests/sim/simulation.rs index b2e696d3..c5d5445c 100644 --- a/tests/sim/simulation.rs +++ b/crates/trippy-core/tests/sim/simulation.rs @@ -1,6 +1,6 @@ use serde::Deserialize; use std::net::IpAddr; -use trippy::tracing::Port; +use trippy_core::Port; /// A simulated trace. #[derive(Debug, Deserialize)] @@ -70,7 +70,7 @@ pub enum PrivilegeMode { Unprivileged, } -impl From for trippy::tracing::PrivilegeMode { +impl From for trippy_core::PrivilegeMode { fn from(value: PrivilegeMode) -> Self { match value { PrivilegeMode::Privileged => Self::Privileged, @@ -86,7 +86,7 @@ pub enum Protocol { Tcp, } -impl From for trippy::tracing::Protocol { +impl From for trippy_core::Protocol { fn from(value: Protocol) -> Self { match value { Protocol::Icmp => Self::Icmp, @@ -111,7 +111,7 @@ pub struct FixedBoth { pub dest: u16, } -impl From for trippy::tracing::PortDirection { +impl From for trippy_core::PortDirection { fn from(value: PortDirection) -> Self { match value { PortDirection::None => Self::None, @@ -132,7 +132,7 @@ pub enum MultipathStrategy { Dublin, } -impl From for trippy::tracing::MultipathStrategy { +impl From for trippy_core::MultipathStrategy { fn from(value: MultipathStrategy) -> Self { match value { MultipathStrategy::Classic => Self::Classic, diff --git a/tests/sim/tests.rs b/crates/trippy-core/tests/sim/tests.rs similarity index 100% rename from tests/sim/tests.rs rename to crates/trippy-core/tests/sim/tests.rs diff --git a/tests/sim/tracer.rs b/crates/trippy-core/tests/sim/tracer.rs similarity index 99% rename from tests/sim/tracer.rs rename to crates/trippy-core/tests/sim/tracer.rs index 738d06b7..b3c520fc 100644 --- a/tests/sim/tracer.rs +++ b/crates/trippy-core/tests/sim/tracer.rs @@ -6,7 +6,7 @@ use std::thread; use std::time::Duration; use tokio_util::sync::CancellationToken; use tracing::info; -use trippy::tracing::{ +use trippy_core::{ defaults, Builder, CompletionReason, MaxRounds, MultipathStrategy, PacketSize, PayloadPattern, PortDirection, PrivilegeMode, ProbeState, Protocol, Sequence, TimeToLive, TraceId, TracerRound, }; diff --git a/tests/sim/tun_device.rs b/crates/trippy-core/tests/sim/tun_device.rs similarity index 100% rename from tests/sim/tun_device.rs rename to crates/trippy-core/tests/sim/tun_device.rs diff --git a/crates/trippy-dns/Cargo.toml b/crates/trippy-dns/Cargo.toml new file mode 100644 index 00000000..65ea95ac --- /dev/null +++ b/crates/trippy-dns/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "trippy-dns" +description = "A lazy DNS resolver for Trippy" +version.workspace = true +authors.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +keywords = ["traceroute", "ping", "icmp"] +categories = ["network-programming"] + +[dependencies] +thiserror.workspace = true +itertools.workspace = true +crossbeam = "0.8.4" +dns-lookup = "2.0.4" +hickory-resolver = "0.24.1" +parking_lot.workspace = true + +[dev-dependencies] +anyhow.workspace = true \ No newline at end of file diff --git a/src/dns/lazy_resolver.rs b/crates/trippy-dns/src/lazy_resolver.rs similarity index 88% rename from src/dns/lazy_resolver.rs rename to crates/trippy-dns/src/lazy_resolver.rs index 366c3652..95991c82 100644 --- a/src/dns/lazy_resolver.rs +++ b/crates/trippy-dns/src/lazy_resolver.rs @@ -1,4 +1,4 @@ -use crate::dns::resolver::{DnsEntry, ResolvedIpAddrs, Resolver, Result}; +use crate::resolver::{DnsEntry, ResolvedIpAddrs, Resolver, Result}; use std::fmt::{Display, Formatter}; use std::net::IpAddr; use std::rc::Rc; @@ -118,14 +118,12 @@ impl Resolver for DnsResolver { /// Private impl of resolver. mod inner { - use crate::dns::lazy_resolver::{Config, IpAddrFamily, ResolveMethod}; - use crate::dns::resolver::{ - AsInfo, DnsEntry, Error, Resolved, ResolvedIpAddrs, Result, Unresolved, - }; - use anyhow::anyhow; + use super::{Config, IpAddrFamily, ResolveMethod}; + use crate::resolver::{AsInfo, DnsEntry, Error, Resolved, ResolvedIpAddrs, Result, Unresolved}; use crossbeam::channel::{bounded, Receiver, Sender}; use hickory_resolver::config::{LookupIpStrategy, ResolverConfig, ResolverOpts}; - use hickory_resolver::error::ResolveErrorKind; + use hickory_resolver::error::{ResolveError, ResolveErrorKind}; + use hickory_resolver::proto::error::ProtoError; use hickory_resolver::proto::rr::RecordType; use hickory_resolver::{Name, Resolver}; use itertools::{Either, Itertools}; @@ -388,7 +386,7 @@ mod inner { } /// Lookup up `AsInfo` for an `IpAddr` address. - fn lookup_asinfo(resolver: &Arc, addr: IpAddr) -> anyhow::Result { + fn lookup_asinfo(resolver: &Arc, addr: IpAddr) -> Result { let origin_query_txt = match addr { IpAddr::V4(addr) => query_asn_ipv4(resolver, addr)?, IpAddr::V6(addr) => query_asn_ipv6(resolver, addr)?, @@ -407,23 +405,25 @@ mod inner { } /// Perform the `origin` query. - fn query_asn_ipv4(resolver: &Arc, addr: Ipv4Addr) -> anyhow::Result { + fn query_asn_ipv4(resolver: &Arc, addr: Ipv4Addr) -> Result { let query = format!( "{}.origin.asn.cymru.com.", addr.octets().iter().rev().join(".") ); - let name = Name::from_str(query.as_str())?; - let response = resolver.lookup(name, RecordType::TXT)?; + let name = Name::from_str(query.as_str()).map_err(proto_error)?; + let response = resolver + .lookup(name, RecordType::TXT) + .map_err(resolve_error)?; let data = response .iter() .next() - .ok_or_else(|| anyhow!("asn origin query"))?; - let bytes = data.as_txt().ok_or_else(|| anyhow!("asn origin query"))?; + .ok_or_else(|| Error::QueryAsnOriginFailed)?; + let bytes = data.as_txt().ok_or_else(|| Error::QueryAsnOriginFailed)?; Ok(bytes.to_string()) } /// Perform the `origin` query. - fn query_asn_ipv6(resolver: &Arc, addr: Ipv6Addr) -> anyhow::Result { + fn query_asn_ipv6(resolver: &Arc, addr: Ipv6Addr) -> Result { let query = format!( "{:x}.origin6.asn.cymru.com.", addr.octets() @@ -432,23 +432,30 @@ mod inner { .flat_map(|o| [o & 0x0F, (o & 0xF0) >> 4]) .format(".") ); - let name = Name::from_str(query.as_str())?; - let response = resolver.lookup(name, RecordType::TXT)?; + let name = Name::from_str(query.as_str()).map_err(proto_error)?; + let response = resolver + .lookup(name, RecordType::TXT) + .map_err(resolve_error)?; let data = response .iter() .next() - .ok_or_else(|| anyhow!("asn origin6 query"))?; - let bytes = data.as_txt().ok_or_else(|| anyhow!("asn origin6 query"))?; + .ok_or_else(|| Error::QueryAsnOriginFailed)?; + let bytes = data.as_txt().ok_or_else(|| Error::QueryAsnOriginFailed)?; Ok(bytes.to_string()) } /// Perform the `asn` query. - fn query_asn_name(resolver: &Arc, asn: &str) -> anyhow::Result { + fn query_asn_name(resolver: &Arc, asn: &str) -> Result { let query = format!("AS{asn}.asn.cymru.com."); - let name = Name::from_str(query.as_str())?; - let response = resolver.lookup(name, RecordType::TXT)?; - let data = response.iter().next().ok_or_else(|| anyhow!("asn query"))?; - let bytes = data.as_txt().ok_or_else(|| anyhow!("asn query"))?; + let name = Name::from_str(query.as_str()).map_err(proto_error)?; + let response = resolver + .lookup(name, RecordType::TXT) + .map_err(resolve_error)?; + let data = response + .iter() + .next() + .ok_or_else(|| Error::QueryAsnFailed)?; + let bytes = data.as_txt().ok_or_else(|| Error::QueryAsnFailed)?; Ok(bytes.to_string()) } @@ -459,12 +466,11 @@ mod inner { /// `12301 | 81.0.100.0/22 | HU | ripencc | 2001-12-06` /// /// From this we extract all fields. - fn parse_origin_query_txt(origin_query_txt: &str) -> anyhow::Result { + fn parse_origin_query_txt(origin_query_txt: &str) -> Result { if origin_query_txt.chars().filter(|c| *c == '|').count() != 4 { - return Err(anyhow!( - "failed to parse AS origin txt: {}", - origin_query_txt - )); + return Err(Error::ParseOriginQueryFailed(String::from( + origin_query_txt, + ))); } let mut split = origin_query_txt.split('|'); let asn = split.next().unwrap_or_default().trim().to_string(); @@ -489,11 +495,21 @@ mod inner { /// `12301 | HU | ripencc | 1999-02-25 | INVITECH, HU` /// /// From this we extract the 4th field (name, `INVITECH, HU` in this example) - fn parse_asn_query_txt(asn_query_txt: &str) -> anyhow::Result { + fn parse_asn_query_txt(asn_query_txt: &str) -> Result { if asn_query_txt.chars().filter(|c| *c == '|').count() != 4 { - return Err(anyhow!("failed to parse AS origin txt: {}", asn_query_txt)); + return Err(Error::ParseAsnQueryFailed(String::from(asn_query_txt))); } let mut split = asn_query_txt.split('|'); Ok(split.nth(4).unwrap_or_default().trim().to_string()) } + + /// Convert a `ResolveError` to an `Error::LookupFailed`. + fn resolve_error(err: ResolveError) -> Error { + Error::LookupFailed(Box::new(err)) + } + + /// Convert a `ProtoError` to an `Error::LookupFailed`. + fn proto_error(err: ProtoError) -> Error { + Error::LookupFailed(Box::new(err)) + } } diff --git a/crates/trippy-dns/src/lib.rs b/crates/trippy-dns/src/lib.rs new file mode 100644 index 00000000..5fb7d5a1 --- /dev/null +++ b/crates/trippy-dns/src/lib.rs @@ -0,0 +1,83 @@ +//! This crate provides a cheaply cloneable, non-blocking, caching, forward +//! and reverse DNS resolver which support the ability to lookup Autonomous +//! System (AS) information. +//! +//! # Example +//! +//! The following example perform a reverse DNS lookup and loop until it is +//! resolved or fails. The lookup uses the Cloudflare 1.1.1.1 public DNS +//! service. +//! +//! Note that only a single reverse DNS lookup is performed (lazily) regardless +//! of how often the lookup is performed, unless the previous lookup failed +//! with `DnsEntry::Timeout(_)`. +//! +//! ```no_run +//! # fn main() -> anyhow::Result<()> { +//! # use std::net::IpAddr; +//! # use std::str::FromStr; +//! # use std::thread::sleep; +//! # use std::time::Duration; +//! use trippy_dns::{ +//! Config, DnsEntry, DnsResolver, IpAddrFamily, ResolveMethod, Resolved, Resolver, Unresolved, +//! }; +//! +//! let config = Config::new( +//! ResolveMethod::Cloudflare, +//! IpAddrFamily::Ipv4Only, +//! Duration::from_secs(5), +//! ); +//! let resolver = DnsResolver::start(config)?; +//! let addr = IpAddr::from_str("1.1.1.1")?; +//! loop { +//! let entry = resolver.lazy_reverse_lookup_with_asinfo(addr); +//! match entry { +//! DnsEntry::Pending(ip) => { +//! println!("lookup of {ip} is pending, sleeping for 1 sec"); +//! sleep(Duration::from_secs(1)); +//! } +//! DnsEntry::Resolved(Resolved::Normal(ip, addrs)) => { +//! println!("lookup of {ip} resolved to {addrs:?}"); +//! return Ok(()); +//! } +//! DnsEntry::Resolved(Resolved::WithAsInfo(ip, addrs, as_info)) => { +//! println!("lookup of {ip} resolved to {addrs:?} with AS information {as_info:?}"); +//! return Ok(()); +//! } +//! DnsEntry::NotFound(Unresolved::Normal(ip)) => { +//! println!("lookup of {ip} did not match any records"); +//! return Ok(()); +//! } +//! DnsEntry::NotFound(Unresolved::WithAsInfo(ip, as_info)) => { +//! println!( +//! "lookup of {ip} did not match any records with AS information {as_info:?}" +//! ); +//! return Ok(()); +//! } +//! DnsEntry::Timeout(ip) => { +//! println!("lookup of {ip} timed out"); +//! return Ok(()); +//! } +//! DnsEntry::Failed(ip) => { +//! println!("lookup of {ip} failed"); +//! return Ok(()); +//! } +//! } +//! } +//! # Ok(()) +//! # } +//! ``` +#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)] +#![allow( + clippy::module_name_repetitions, + clippy::missing_const_for_fn, + clippy::missing_errors_doc, + clippy::option_if_let_else +)] +#![forbid(unsafe_code)] + +mod lazy_resolver; +mod resolver; + +pub use lazy_resolver::{Config, DnsResolver, IpAddrFamily, ResolveMethod}; +pub use resolver::{AsInfo, DnsEntry, Error, Resolved, Resolver, Result, Unresolved}; diff --git a/src/dns/resolver.rs b/crates/trippy-dns/src/resolver.rs similarity index 94% rename from src/dns/resolver.rs rename to crates/trippy-dns/src/resolver.rs index b0acc36f..02057918 100644 --- a/src/dns/resolver.rs +++ b/crates/trippy-dns/src/resolver.rs @@ -49,6 +49,14 @@ pub type Result = std::result::Result; pub enum Error { #[error("DNS lookup failed")] LookupFailed(Box), + #[error("ASN origin query failed")] + QueryAsnOriginFailed, + #[error("ASN query failed")] + QueryAsnFailed, + #[error("origin query txt parse failed: {0}")] + ParseOriginQueryFailed(String), + #[error("asn query txt parse failed: {0}")] + ParseAsnQueryFailed(String), } /// The output of a successful DNS lookup. diff --git a/crates/trippy-privilege/Cargo.toml b/crates/trippy-privilege/Cargo.toml new file mode 100644 index 00000000..121f7274 --- /dev/null +++ b/crates/trippy-privilege/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "trippy-privilege" +description = "Discover platform privileges" +version.workspace = true +authors.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +keywords = ["traceroute", "ping", "icmp"] +categories = ["network-programming"] + +[dependencies] +thiserror.workspace = true + +[target.'cfg(target_os = "linux")'.dependencies] +caps = "0.5.5" + +[target.'cfg(unix)'.dependencies] +nix = { version = "0.28.0", default-features = false, features = [ "user" ] } + +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.52.0", features = [ + "Win32_Foundation", + "Win32_System_Threading", +] } +paste = "1.0.15" + +[dev-dependencies] +anyhow.workspace = true \ No newline at end of file diff --git a/src/platform.rs b/crates/trippy-privilege/src/lib.rs similarity index 54% rename from src/platform.rs rename to crates/trippy-privilege/src/lib.rs index c4745609..ed3b7f47 100644 --- a/src/platform.rs +++ b/crates/trippy-privilege/src/lib.rs @@ -1,37 +1,146 @@ -/// Runtime information about the platform and environment. +//! Discover platform privileges. +//! +//! A cross-platform library to discover and manage platform privileges needed +//! for sending ICMP packets via RAW and `IPPROTO_ICMP` sockets. +//! +//! [`Privilege::acquire_privileges`]: +//! +//! - On Linux we check if `CAP_NET_RAW` is in the permitted set and if so raise +//! it to the effective set +//! - On other Unix platforms this is a no-op +//! - On Windows this is a no-op +//! +//! [`Privilege::has_privileges`] (obtained via [`Privilege::discover`]): +//! +//! - On Linux we check if `CAP_NET_RAW` is in the effective set +//! - On other Unix platforms we check that the effective user is root +//! - On Windows we check if the current process has an elevated token +//! +//! [`Privilege::needs_privileges`] (obtained via [`Privilege::discover`]): +//! +//! - On macOS we do not always need privileges to send ICMP packets as we +//! can use `IPPROTO_ICMP` sockets with the `IP_HDRINCL` socket option. +//! - On Linux we always need privileges to send ICMP packets even though it +//! supports the `IPPROTO_ICMP` socket type but not the `IP_HDRINCL` socket option +//! - On Windows we always need privileges to send ICMP packets +//! +//! [`Privilege::drop_privileges`]: +//! +//! - On Linux we clear the effective set +//! - On other Unix platforms this is a no-op +//! - On Windows this is a no-op +//! +//! # Examples +//! +//! Acquire the required privileges if we can: +//! +//! ```rust +//! # fn main() -> anyhow::Result<()> { +//! # use trippy_privilege::Privilege; +//! Privilege::acquire_privileges()?; +//! # Ok(()) +//! # } +//! ``` +//! +//! Discover the current privileges: +//! +//! ```rust +//! # fn main() -> anyhow::Result<()> { +//! # use trippy_privilege::Privilege; +//! let privilege = Privilege::discover()?; +//! if privilege.has_privileges() { +//! println!("You have the required privileges for raw sockets"); +//! } else { +//! println!("You do not have the required privileges for raw sockets"); +//! } +//! if privilege.needs_privileges() { +//! println!("You always need privileges to send ICMP packets."); +//! } else { +//! println!("You do not always need privileges to send ICMP packets."); +//! } +//! # Ok(()) +//! # } +//! ``` +//! +//! Drop all privileges: +//! +//! ```rust +//! # fn main() -> anyhow::Result<()> { +//! # use trippy_privilege::Privilege; +//! Privilege::drop_privileges()?; +//! # Ok(()) +//! # } +//! ``` +#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)] +#![allow(clippy::missing_const_for_fn, clippy::missing_errors_doc)] +#![deny(unsafe_code)] + +/// A privilege error result. +pub type Result = std::result::Result; + +/// A privilege error. +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[cfg(target_os = "linux")] + #[error("caps error: {0}")] + CapsError(#[from] caps::errors::CapsError), + #[cfg(windows)] + #[error("OpenProcessToken failed")] + OpenProcessTokenError, + #[cfg(windows)] + #[error("GetTokenInformation failed")] + GetTokenInformationError, +} + +/// Runtime platform privilege information. #[derive(Debug)] -pub struct Platform { - /// The platform process id. - pub pid: u16, - /// Are we running with the privileges required for raw sockets? - pub has_privileges: bool, - /// Does our platform always need privileges for `ICMP`? - /// - /// Specifically, each platform requires privileges unless it supports the `IPPROTO_ICMP` socket type which _also_ - /// allows the `IP_HDRINCL` socket option to be set. - pub needs_privileges: bool, +pub struct Privilege { + has_privileges: bool, + needs_privileges: bool, } -impl Platform { - /// Discover information about the platform and environment. - pub fn discover() -> anyhow::Result { - let pid = u16::try_from(std::process::id() % u32::from(u16::MAX))?; - let has_privileges = Self::has_privileges()?; - let needs_privileges = Self::needs_privileges(); +impl Privilege { + /// Discover information about the platform privileges. + pub fn discover() -> Result { + let has_privileges = Self::check_has_privileges()?; + let needs_privileges = Self::check_needs_privileges(); Ok(Self { - pid, has_privileges, needs_privileges, }) } + /// Create a new Privilege instance. + #[must_use] + pub fn new(has_privileges: bool, needs_privileges: bool) -> Self { + Self { + has_privileges, + needs_privileges, + } + } + + /// Are we running with the privileges required for raw sockets? + #[must_use] + pub fn has_privileges(&self) -> bool { + self.has_privileges + } + + /// Does our platform always need privileges for `ICMP`? + /// + /// Specifically, each platform requires privileges unless it supports the `IPPROTO_ICMP` socket type which _also_ + /// allows the `IP_HDRINCL` socket option to be set. + #[must_use] + pub fn needs_privileges(&self) -> bool { + self.needs_privileges + } + // Linux #[cfg(target_os = "linux")] /// Acquire privileges, if possible. /// /// Check if `CAP_NET_RAW` is in the permitted set and if so raise it to the effective set. - pub fn acquire_privileges() -> anyhow::Result<()> { + pub fn acquire_privileges() -> Result<()> { if caps::has_cap(None, caps::CapSet::Permitted, caps::Capability::CAP_NET_RAW)? { caps::raise(None, caps::CapSet::Effective, caps::Capability::CAP_NET_RAW)?; } @@ -42,7 +151,7 @@ impl Platform { /// Do we have the required privileges? /// /// Check if `CAP_NET_RAW` is in the effective set. - pub fn has_privileges() -> anyhow::Result { + fn check_has_privileges() -> Result { Ok(caps::has_cap( None, caps::CapSet::Effective, @@ -54,7 +163,7 @@ impl Platform { /// Drop all privileges. /// /// Clears the effective set. - pub fn drop_privileges() -> anyhow::Result<()> { + pub fn drop_privileges() -> Result<()> { caps::clear(None, caps::CapSet::Effective)?; Ok(()) } @@ -66,7 +175,7 @@ impl Platform { /// Acquire privileges, if possible. /// /// This is a no-op on non-Linux unix systems. - pub fn acquire_privileges() -> anyhow::Result<()> { + pub fn acquire_privileges() -> Result<()> { Ok(()) } @@ -75,7 +184,7 @@ impl Platform { /// Do we have the required privileges? /// /// Checks if the effective user is root. - pub fn has_privileges() -> anyhow::Result { + fn check_has_privileges() -> Result { Ok(nix::unistd::Uid::effective().is_root()) } @@ -84,7 +193,7 @@ impl Platform { /// Drop all privileges. /// /// This is a no-op on non-Linux unix systems. - pub fn drop_privileges() -> anyhow::Result<()> { + pub fn drop_privileges() -> Result<()> { Ok(()) } @@ -97,7 +206,7 @@ impl Platform { /// option and is therefore not supported. This may be supported in the future. /// /// `NetBSD`, `OpenBSD` and `FreeBSD` do not support `IPPROTO_ICMP`. - fn needs_privileges() -> bool { + fn check_needs_privileges() -> bool { true } @@ -107,7 +216,7 @@ impl Platform { /// Does the platform always require privileges? /// /// `macOS` supports both privileged and unprivileged modes. - fn needs_privileges() -> bool { + fn check_needs_privileges() -> bool { false } @@ -118,7 +227,7 @@ impl Platform { /// Acquire privileges, if possible. /// /// This is a no-op on `Windows`. - pub fn acquire_privileges() -> anyhow::Result<()> { + pub fn acquire_privileges() -> Result<()> { Ok(()) } @@ -127,7 +236,7 @@ impl Platform { /// Do we have the required privileges? /// /// Check if the current process has an elevated token. - pub fn has_privileges() -> anyhow::Result { + fn check_has_privileges() -> Result { macro_rules! syscall { ($p: path, $fn: ident ( $($arg: expr),* $(,)* ) ) => {{ #[allow(unsafe_code)] @@ -142,7 +251,7 @@ impl Platform { impl Privileged { /// Create a new `ElevationChecker` for the current process. - pub fn current_process() -> anyhow::Result { + pub fn current_process() -> Result { use windows_sys::Win32::Security::TOKEN_QUERY; let mut handle: windows_sys::Win32::Foundation::HANDLE = 0; let current_process = syscall!(System::Threading, GetCurrentProcess()); @@ -151,18 +260,19 @@ impl Platform { OpenProcessToken(current_process, TOKEN_QUERY, std::ptr::addr_of_mut!(handle)) ); if res == 0 { - Err(anyhow::anyhow!("OpenProcessToken failed")) + Err(Error::OpenProcessTokenError) } else { Ok(Self { handle }) } } /// Check if the current process has elevated privileged. - pub fn is_elevated(&self) -> anyhow::Result { + pub fn is_elevated(&self) -> Result { use windows_sys::Win32::Security::TokenElevation; use windows_sys::Win32::Security::TOKEN_ELEVATION; let mut elevation = TOKEN_ELEVATION { TokenIsElevated: 0 }; - let size = std::mem::size_of::(); + #[allow(clippy::cast_possible_truncation)] + let size = std::mem::size_of::() as u32; let mut ret_size = 0u32; let ret = syscall!( Security, @@ -170,12 +280,12 @@ impl Platform { self.handle, TokenElevation, std::ptr::addr_of_mut!(elevation).cast(), - size as u32, + size, std::ptr::addr_of_mut!(ret_size), ) ); if ret == 0 { - Err(anyhow::anyhow!("GetTokenInformation failed")) + Err(Error::GetTokenInformationError) } else { Ok(elevation.TokenIsElevated != 0) } @@ -197,7 +307,7 @@ impl Platform { /// Drop all capabilities. /// /// This is a no-op on `Windows`. - pub fn drop_privileges() -> anyhow::Result<()> { + pub fn drop_privileges() -> Result<()> { Ok(()) } @@ -205,16 +315,7 @@ impl Platform { /// Does the platform always require privileges? /// /// Privileges are always required on `Windows`. - fn needs_privileges() -> bool { + fn check_needs_privileges() -> bool { true } - - #[cfg(test)] - pub fn dummy_for_test() -> Self { - Self { - pid: 0, - has_privileges: true, - needs_privileges: false, - } - } } diff --git a/crates/trippy/Cargo.toml b/crates/trippy/Cargo.toml new file mode 100644 index 00000000..ea59d836 --- /dev/null +++ b/crates/trippy/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "trippy" +description = "A network diagnostic tool" +version.workspace = true +authors.workspace = true +documentation.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true +keywords = ["cli", "tui", "traceroute", "ping", "icmp"] +categories = ["command-line-utilities", "network-programming"] + +[[bin]] +bench = false +path = "src/main.rs" +name = "trip" + +[dependencies] +trippy-core = { version = "0.11.0-dev", path = "../trippy-core" } +trippy-privilege = { version = "0.11.0-dev", path = "../trippy-privilege" } +trippy-dns = { version = "0.11.0-dev", path = "../trippy-dns" } +thiserror.workspace = true +anyhow.workspace = true +itertools.workspace = true +tracing.workspace = true +serde.workspace = true +derive_more.workspace = true +parking_lot.workspace = true +clap = { version = "4.4.0", default-features = false, features = [ "cargo", "derive", "wrap_help", "usage", "unstable-styles" ] } +clap_complete = "4.4.9" +humantime = "2.1.0" +ratatui = "0.26.2" +crossterm = { version = "0.27.0", default-features = false, features = [ "events", "windows" ] } +chrono = { version = "0.4.38", default-features = false, features = [ "clock" ] } +serde_json = { version = "1.0.117", default-features = false } +comfy-table = { version = "7.1.0", default-features = false } +strum = { version = "0.26.2", default-features = false, features = [ "std", "derive" ] } +etcetera = "0.8.0" +toml = { version = "0.8.13", default-features = false, features = [ "parse" ] } +indexmap = { version = "2.2.6", default-features = false } +maxminddb = "0.24.0" +tracing-subscriber = { version = "0.3.18", default-features = false, features = [ "json", "env-filter" ] } +tracing-chrome = "0.7.2" +petgraph = "0.6.5" +csv = "1.3.0" +serde_with = "3.8.1" +encoding_rs_io = "0.1.7" +clap_mangen = "0.2.20" + +[dev-dependencies] +test-case.workspace = true +serde_yaml.workspace = true +pretty_assertions = "1.4.0" + +[package.metadata.generate-rpm] +assets = [ + { source = "target/release/trip", dest = "/usr/bin/trip", mode = "755" }, +] diff --git a/src/backend.rs b/crates/trippy/src/backend.rs similarity index 91% rename from src/backend.rs rename to crates/trippy/src/backend.rs index 73b3e385..4647eb25 100644 --- a/src/backend.rs +++ b/crates/trippy/src/backend.rs @@ -1,10 +1,10 @@ -use crate::platform::Platform; use parking_lot::RwLock; use std::fmt::Debug; use std::sync::Arc; use trace::Trace; use tracing::instrument; -use trippy::tracing::{ChannelConfig, Config, SocketImpl, Tracer, TracerChannel}; +use trippy_core::{ChannelConfig, Config, SocketImpl, Tracer, TracerChannel}; +use trippy_privilege::Privilege; pub mod flows; pub mod trace; @@ -48,7 +48,7 @@ impl Backend { td.write().set_error(Some(err.to_string())); err })?; - Platform::drop_privileges()?; + Privilege::drop_privileges()?; let tracer = Tracer::new(&self.tracer_config, move |round| { self.trace.write().update_from_round(round); }); diff --git a/src/backend/flows.rs b/crates/trippy/src/backend/flows.rs similarity index 100% rename from src/backend/flows.rs rename to crates/trippy/src/backend/flows.rs diff --git a/src/backend/trace.rs b/crates/trippy/src/backend/trace.rs similarity index 99% rename from src/backend/trace.rs rename to crates/trippy/src/backend/trace.rs index ae473e98..48583791 100644 --- a/src/backend/trace.rs +++ b/crates/trippy/src/backend/trace.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use std::iter::once; use std::net::IpAddr; use std::time::Duration; -use trippy::tracing::{Extensions, IcmpPacketType, ProbeState, Round, TimeToLive, TracerRound}; +use trippy_core::{Extensions, IcmpPacketType, ProbeState, Round, TimeToLive, TracerRound}; /// The state of all hops in a trace. #[derive(Debug, Clone)] @@ -488,7 +488,7 @@ mod tests { use std::str::FromStr; use std::time::SystemTime; use test_case::test_case; - use trippy::tracing::{ + use trippy_core::{ CompletionReason, Flags, IcmpPacketType, Port, Probe, ProbeComplete, ProbeState, Sequence, TimeToLive, TraceId, }; diff --git a/src/config.rs b/crates/trippy/src/config.rs similarity index 98% rename from src/config.rs rename to crates/trippy/src/config.rs index 87b7666a..8b17e7bd 100644 --- a/src/config.rs +++ b/crates/trippy/src/config.rs @@ -1,4 +1,3 @@ -use crate::platform::Platform; use anyhow::anyhow; use clap::ValueEnum; use clap_complete::Shell; @@ -10,10 +9,10 @@ use std::collections::HashMap; use std::net::IpAddr; use std::str::FromStr; use std::time::Duration; -use trippy::dns::{IpAddrFamily, ResolveMethod}; -use trippy::tracing::{ +use trippy_core::{ defaults, IcmpExtensionParseMode, MultipathStrategy, PortDirection, PrivilegeMode, Protocol, }; +use trippy_dns::{IpAddrFamily, ResolveMethod}; mod binding; mod cmd; @@ -27,6 +26,7 @@ pub use cmd::Args; pub use columns::{TuiColumn, TuiColumns}; pub use constants::MAX_HOPS; pub use theme::{TuiColor, TuiTheme, TuiThemeItem}; +use trippy_privilege::Privilege; /// The tool mode. #[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum, Deserialize)] @@ -260,7 +260,7 @@ pub enum TrippyAction { } impl TrippyAction { - pub fn from(args: Args, platform: &Platform) -> anyhow::Result { + pub fn from(args: Args, privilege: &Privilege, pid: u16) -> anyhow::Result { Ok(if args.print_tui_theme_items { Self::PrintTuiThemeItems } else if args.print_tui_binding_commands { @@ -272,7 +272,7 @@ impl TrippyAction { } else if args.generate_man { Self::PrintManPage } else { - Self::Trippy(TrippyConfig::from(args, platform)?) + Self::Trippy(TrippyConfig::from(args, privilege, pid)?) }) } } @@ -328,7 +328,7 @@ pub struct TrippyConfig { } impl TrippyConfig { - pub fn from(args: Args, platform: &Platform) -> anyhow::Result { + pub fn from(args: Args, privilege: &Privilege, pid: u16) -> anyhow::Result { let cfg_file = if let Some(cfg) = &args.config_file { file::read_config_file(cfg)? } else if let Some(cfg) = file::read_default_config_file()? { @@ -336,7 +336,7 @@ impl TrippyConfig { } else { ConfigFile::default() }; - Self::build_config(args, cfg_file, platform) + Self::build_config(args, cfg_file, privilege, pid) } /// The maximum number of flows allowed. @@ -350,12 +350,14 @@ impl TrippyConfig { } #[allow(clippy::too_many_lines)] - fn build_config(args: Args, cfg_file: ConfigFile, platform: &Platform) -> anyhow::Result { - let &Platform { - pid, - has_privileges, - needs_privileges, - } = platform; + fn build_config( + args: Args, + cfg_file: ConfigFile, + privilege: &Privilege, + pid: u16, + ) -> anyhow::Result { + let has_privileges = privilege.has_privileges(); + let needs_privileges = privilege.needs_privileges(); let cfg_file_trace = cfg_file.trippy.unwrap_or_default(); let cfg_file_strategy = cfg_file.strategy.unwrap_or_default(); let cfg_file_tui_bindings = cfg_file.bindings.unwrap_or_default(); @@ -1117,14 +1119,14 @@ mod tests { use crossterm::event::KeyCode; use std::net::{Ipv4Addr, Ipv6Addr}; use test_case::test_case; - use trippy::tracing::Port; + use trippy_core::Port; #[test] fn test_config_default() { let args = args(&["trip", "example.com"]).unwrap(); let cfg_file = ConfigFile::default(); - let platform = Platform::dummy_for_test(); - let config = TrippyConfig::build_config(args, cfg_file, &platform).unwrap(); + let platform = dummy_platform(); + let config = TrippyConfig::build_config(args, cfg_file, &platform, 0).unwrap(); let expected = TrippyConfig { targets: vec![String::from("example.com")], ..TrippyConfig::default() @@ -1136,9 +1138,9 @@ mod tests { fn test_config_sample() { let args = args(&["trip", "example.com"]).unwrap(); let cfg_file: ConfigFile = - toml::from_str(include_str!("../trippy-config-sample.toml")).unwrap(); - let platform = Platform::dummy_for_test(); - let config = TrippyConfig::build_config(args, cfg_file, &platform).unwrap(); + toml::from_str(include_str!("../../../trippy-config-sample.toml")).unwrap(); + let platform = dummy_platform(); + let config = TrippyConfig::build_config(args, cfg_file, &platform, 0).unwrap(); let expected = TrippyConfig { targets: vec![String::from("example.com")], ..TrippyConfig::default() @@ -1620,14 +1622,14 @@ mod tests { } fn parse_action(cmd: &str) -> anyhow::Result { - TrippyAction::from(parse(cmd)?, &Platform::dummy_for_test()) + TrippyAction::from(parse(cmd)?, &dummy_platform(), 0) } fn parse_config(cmd: &str) -> anyhow::Result { let args = parse(cmd)?; let cfg_file = ConfigFile::default(); - let platform = Platform::dummy_for_test(); - TrippyConfig::build_config(args, cfg_file, &platform) + let platform = dummy_platform(); + TrippyConfig::build_config(args, cfg_file, &platform, 0) } fn parse_config_with_privileges( @@ -1637,12 +1639,8 @@ mod tests { ) -> anyhow::Result { let args = parse(cmd)?; let cfg_file = ConfigFile::default(); - let platform = Platform { - pid: 0, - has_privileges, - needs_privileges, - }; - TrippyConfig::build_config(args, cfg_file, &platform) + let privilege = Privilege::new(has_privileges, needs_privileges); + TrippyConfig::build_config(args, cfg_file, &privilege, 0) } fn parse(cmd: &str) -> anyhow::Result { @@ -1686,6 +1684,10 @@ mod tests { ]) } + fn dummy_platform() -> Privilege { + Privilege::new(true, false) + } + fn args(args: &[&str]) -> anyhow::Result { use clap::Parser; Ok(Args::try_parse_from( diff --git a/src/config/binding.rs b/crates/trippy/src/config/binding.rs similarity index 100% rename from src/config/binding.rs rename to crates/trippy/src/config/binding.rs diff --git a/src/config/cmd.rs b/crates/trippy/src/config/cmd.rs similarity index 100% rename from src/config/cmd.rs rename to crates/trippy/src/config/cmd.rs diff --git a/src/config/columns.rs b/crates/trippy/src/config/columns.rs similarity index 100% rename from src/config/columns.rs rename to crates/trippy/src/config/columns.rs diff --git a/src/config/constants.rs b/crates/trippy/src/config/constants.rs similarity index 100% rename from src/config/constants.rs rename to crates/trippy/src/config/constants.rs diff --git a/src/config/file.rs b/crates/trippy/src/config/file.rs similarity index 99% rename from src/config/file.rs rename to crates/trippy/src/config/file.rs index a9fe30c0..7e4113e8 100644 --- a/src/config/file.rs +++ b/crates/trippy/src/config/file.rs @@ -12,7 +12,7 @@ use serde::Deserialize; use std::fs::File; use std::io::{BufReader, Read}; use std::path::Path; -use trippy::tracing::defaults; +use trippy_core::defaults; const DEFAULT_CONFIG_FILE: &str = "trippy.toml"; const DEFAULT_HIDDEN_CONFIG_FILE: &str = ".trippy.toml"; @@ -407,7 +407,7 @@ mod tests { #[allow(clippy::too_many_lines)] fn test_parse_config_sample() { let config: ConfigFile = - toml::from_str(include_str!("../../trippy-config-sample.toml")).unwrap(); + toml::from_str(include_str!("../../../../trippy-config-sample.toml")).unwrap(); pretty_assertions::assert_eq!(ConfigFile::default(), config); } } diff --git a/src/config/theme.rs b/crates/trippy/src/config/theme.rs similarity index 100% rename from src/config/theme.rs rename to crates/trippy/src/config/theme.rs diff --git a/src/frontend.rs b/crates/trippy/src/frontend.rs similarity index 99% rename from src/frontend.rs rename to crates/trippy/src/frontend.rs index bb22c7ba..64c58bed 100644 --- a/src/frontend.rs +++ b/crates/trippy/src/frontend.rs @@ -14,7 +14,7 @@ use ratatui::{ Terminal, }; use std::io; -use trippy::dns::DnsResolver; +use trippy_dns::DnsResolver; use tui_app::TuiApp; mod binding; diff --git a/src/frontend/binding.rs b/crates/trippy/src/frontend/binding.rs similarity index 100% rename from src/frontend/binding.rs rename to crates/trippy/src/frontend/binding.rs diff --git a/src/frontend/columns.rs b/crates/trippy/src/frontend/columns.rs similarity index 100% rename from src/frontend/columns.rs rename to crates/trippy/src/frontend/columns.rs diff --git a/src/frontend/config.rs b/crates/trippy/src/frontend/config.rs similarity index 100% rename from src/frontend/config.rs rename to crates/trippy/src/frontend/config.rs diff --git a/src/frontend/render.rs b/crates/trippy/src/frontend/render.rs similarity index 100% rename from src/frontend/render.rs rename to crates/trippy/src/frontend/render.rs diff --git a/src/frontend/render/app.rs b/crates/trippy/src/frontend/render/app.rs similarity index 100% rename from src/frontend/render/app.rs rename to crates/trippy/src/frontend/render/app.rs diff --git a/src/frontend/render/body.rs b/crates/trippy/src/frontend/render/body.rs similarity index 100% rename from src/frontend/render/body.rs rename to crates/trippy/src/frontend/render/body.rs diff --git a/src/frontend/render/bsod.rs b/crates/trippy/src/frontend/render/bsod.rs similarity index 100% rename from src/frontend/render/bsod.rs rename to crates/trippy/src/frontend/render/bsod.rs diff --git a/src/frontend/render/chart.rs b/crates/trippy/src/frontend/render/chart.rs similarity index 100% rename from src/frontend/render/chart.rs rename to crates/trippy/src/frontend/render/chart.rs diff --git a/src/frontend/render/flows.rs b/crates/trippy/src/frontend/render/flows.rs similarity index 100% rename from src/frontend/render/flows.rs rename to crates/trippy/src/frontend/render/flows.rs diff --git a/src/frontend/render/footer.rs b/crates/trippy/src/frontend/render/footer.rs similarity index 100% rename from src/frontend/render/footer.rs rename to crates/trippy/src/frontend/render/footer.rs diff --git a/src/frontend/render/header.rs b/crates/trippy/src/frontend/render/header.rs similarity index 98% rename from src/frontend/render/header.rs rename to crates/trippy/src/frontend/render/header.rs index edb9f9af..611eaea7 100644 --- a/src/frontend/render/header.rs +++ b/crates/trippy/src/frontend/render/header.rs @@ -8,8 +8,8 @@ use ratatui::widgets::{Block, BorderType, Borders, Paragraph}; use ratatui::Frame; use std::net::IpAddr; use std::time::Duration; -use trippy::dns::{ResolveMethod, Resolver}; -use trippy::tracing::{PortDirection, Protocol}; +use trippy_core::{PortDirection, Protocol}; +use trippy_dns::{ResolveMethod, Resolver}; /// Render the title, config, target, clock and keyboard controls. #[allow(clippy::too_many_lines)] diff --git a/src/frontend/render/help.rs b/crates/trippy/src/frontend/render/help.rs similarity index 100% rename from src/frontend/render/help.rs rename to crates/trippy/src/frontend/render/help.rs diff --git a/src/frontend/render/histogram.rs b/crates/trippy/src/frontend/render/histogram.rs similarity index 100% rename from src/frontend/render/histogram.rs rename to crates/trippy/src/frontend/render/histogram.rs diff --git a/src/frontend/render/history.rs b/crates/trippy/src/frontend/render/history.rs similarity index 100% rename from src/frontend/render/history.rs rename to crates/trippy/src/frontend/render/history.rs diff --git a/src/frontend/render/settings.rs b/crates/trippy/src/frontend/render/settings.rs similarity index 99% rename from src/frontend/render/settings.rs rename to crates/trippy/src/frontend/render/settings.rs index a18fc700..6ea8ba18 100644 --- a/src/frontend/render/settings.rs +++ b/crates/trippy/src/frontend/render/settings.rs @@ -10,8 +10,8 @@ use ratatui::widgets::{ Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table, Tabs, Wrap, }; use ratatui::Frame; -use trippy::dns::ResolveMethod; -use trippy::tracing::PortDirection; +use trippy_core::PortDirection; +use trippy_dns::ResolveMethod; /// Render settings dialog. pub fn render(f: &mut Frame<'_>, app: &mut TuiApp) { diff --git a/src/frontend/render/splash.rs b/crates/trippy/src/frontend/render/splash.rs similarity index 100% rename from src/frontend/render/splash.rs rename to crates/trippy/src/frontend/render/splash.rs diff --git a/src/frontend/render/table.rs b/crates/trippy/src/frontend/render/table.rs similarity index 99% rename from src/frontend/render/table.rs rename to crates/trippy/src/frontend/render/table.rs index 95ad7aa9..8976d60f 100644 --- a/src/frontend/render/table.rs +++ b/crates/trippy/src/frontend/render/table.rs @@ -12,10 +12,8 @@ use ratatui::widgets::{Block, BorderType, Borders, Cell, Row, Table}; use ratatui::Frame; use std::net::IpAddr; use std::rc::Rc; -use trippy::dns::{AsInfo, DnsEntry, DnsResolver, Resolved, Resolver, Unresolved}; -use trippy::tracing::{ - Extension, Extensions, IcmpPacketType, MplsLabelStackMember, UnknownExtension, -}; +use trippy_core::{Extension, Extensions, IcmpPacketType, MplsLabelStackMember, UnknownExtension}; +use trippy_dns::{AsInfo, DnsEntry, DnsResolver, Resolved, Resolver, Unresolved}; /// Render the table of data about the hops. /// diff --git a/src/frontend/render/tabs.rs b/crates/trippy/src/frontend/render/tabs.rs similarity index 100% rename from src/frontend/render/tabs.rs rename to crates/trippy/src/frontend/render/tabs.rs diff --git a/src/frontend/render/util.rs b/crates/trippy/src/frontend/render/util.rs similarity index 100% rename from src/frontend/render/util.rs rename to crates/trippy/src/frontend/render/util.rs diff --git a/src/frontend/render/world.rs b/crates/trippy/src/frontend/render/world.rs similarity index 100% rename from src/frontend/render/world.rs rename to crates/trippy/src/frontend/render/world.rs diff --git a/src/frontend/theme.rs b/crates/trippy/src/frontend/theme.rs similarity index 100% rename from src/frontend/theme.rs rename to crates/trippy/src/frontend/theme.rs diff --git a/src/frontend/tui_app.rs b/crates/trippy/src/frontend/tui_app.rs similarity index 99% rename from src/frontend/tui_app.rs rename to crates/trippy/src/frontend/tui_app.rs index 1deefbf3..5e53bc1d 100644 --- a/src/frontend/tui_app.rs +++ b/crates/trippy/src/frontend/tui_app.rs @@ -8,7 +8,7 @@ use crate::TraceInfo; use itertools::Itertools; use ratatui::widgets::TableState; use std::time::SystemTime; -use trippy::dns::{DnsResolver, ResolveMethod}; +use trippy_dns::{DnsResolver, ResolveMethod}; pub struct TuiApp { pub selected_tracer_data: Trace, diff --git a/src/geoip.rs b/crates/trippy/src/geoip.rs similarity index 100% rename from src/geoip.rs rename to crates/trippy/src/geoip.rs diff --git a/crates/trippy/src/lib.rs b/crates/trippy/src/lib.rs new file mode 100644 index 00000000..e21f8d18 --- /dev/null +++ b/crates/trippy/src/lib.rs @@ -0,0 +1,2 @@ +#![allow(rustdoc::broken_intra_doc_links, rustdoc::bare_urls)] +#![doc = include_str!("../../../README.md")] diff --git a/src/main.rs b/crates/trippy/src/main.rs similarity index 95% rename from src/main.rs rename to crates/trippy/src/main.rs index 560e7109..c2113365 100644 --- a/src/main.rs +++ b/crates/trippy/src/main.rs @@ -13,14 +13,13 @@ clippy::cognitive_complexity, clippy::option_option )] -#![deny(unsafe_code)] +#![forbid(unsafe_code)] use crate::backend::Backend; use crate::config::{ LogFormat, LogSpanEvents, Mode, TrippyAction, TrippyConfig, TuiCommandItem, TuiThemeItem, }; use crate::geoip::GeoIpLookup; -use crate::platform::Platform; use anyhow::{anyhow, Error}; use backend::trace::Trace; use clap::{CommandFactory, Parser}; @@ -37,26 +36,27 @@ use tracing_chrome::{ChromeLayerBuilder, FlushGuard}; use tracing_subscriber::fmt::format::FmtSpan; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; -use trippy::dns::{DnsResolver, Resolver}; -use trippy::tracing::{ +use trippy_core::{ ChannelConfig, Config, IcmpExtensionParseMode, MultipathStrategy, PlatformImpl, PortDirection, Protocol, SocketImpl, }; -use trippy::tracing::{PrivilegeMode, SourceAddr}; +use trippy_core::{PrivilegeMode, SourceAddr}; +use trippy_dns::{DnsResolver, Resolver}; +use trippy_privilege::Privilege; mod backend; mod config; mod frontend; mod geoip; -mod platform; mod report; fn main() -> anyhow::Result<()> { let args = Args::parse(); - Platform::acquire_privileges()?; - let platform = Platform::discover()?; - match TrippyAction::from(args, &platform)? { - TrippyAction::Trippy(cfg) => run_trippy(&cfg, &platform)?, + Privilege::acquire_privileges()?; + let privilege = Privilege::discover()?; + let pid = u16::try_from(process::id() % u32::from(u16::MAX))?; + match TrippyAction::from(args, &privilege, pid)? { + TrippyAction::Trippy(cfg) => run_trippy(&cfg, pid)?, TrippyAction::PrintTuiThemeItems => print_tui_theme_items(), TrippyAction::PrintTuiBindingCommands => print_tui_binding_commands(), TrippyAction::PrintConfigTemplate => print_config_template(), @@ -66,7 +66,7 @@ fn main() -> anyhow::Result<()> { Ok(()) } -fn run_trippy(cfg: &TrippyConfig, platform: &Platform) -> anyhow::Result<()> { +fn run_trippy(cfg: &TrippyConfig, pid: u16) -> anyhow::Result<()> { let _guard = configure_logging(cfg); let resolver = start_dns_resolver(cfg)?; let geoip_lookup = create_geoip_lookup(cfg)?; @@ -78,8 +78,8 @@ fn run_trippy(cfg: &TrippyConfig, platform: &Platform) -> anyhow::Result<()> { cfg.addr_family, )); } - let traces = start_tracers(cfg, &addrs, platform.pid)?; - Platform::drop_privileges()?; + let traces = start_tracers(cfg, &addrs, pid)?; + Privilege::drop_privileges()?; run_frontend(cfg, resolver, geoip_lookup, traces) } @@ -94,7 +94,7 @@ fn print_tui_binding_commands() { } fn print_config_template() { - println!("{}", include_str!("../trippy-config-sample.toml")); + println!("{}", include_str!("../../../trippy-config-sample.toml")); process::exit(0); } @@ -110,7 +110,7 @@ fn print_man_page() -> anyhow::Result<()> { /// Start the DNS resolver. fn start_dns_resolver(cfg: &TrippyConfig) -> anyhow::Result { - Ok(DnsResolver::start(trippy::dns::Config::new( + Ok(DnsResolver::start(trippy_dns::Config::new( cfg.dns_resolve_method, cfg.addr_family, cfg.dns_timeout, diff --git a/src/report.rs b/crates/trippy/src/report.rs similarity index 100% rename from src/report.rs rename to crates/trippy/src/report.rs diff --git a/src/report/csv.rs b/crates/trippy/src/report/csv.rs similarity index 99% rename from src/report/csv.rs rename to crates/trippy/src/report/csv.rs index bd9b87d0..ebdf5fe7 100644 --- a/src/report/csv.rs +++ b/crates/trippy/src/report/csv.rs @@ -4,7 +4,7 @@ use crate::{backend, TraceInfo}; use itertools::Itertools; use serde::Serialize; use std::net::IpAddr; -use trippy::dns::Resolver; +use trippy_dns::Resolver; /// Generate a CSV report of trace data. pub fn report( diff --git a/src/report/dot.rs b/crates/trippy/src/report/dot.rs similarity index 100% rename from src/report/dot.rs rename to crates/trippy/src/report/dot.rs diff --git a/src/report/flows.rs b/crates/trippy/src/report/flows.rs similarity index 100% rename from src/report/flows.rs rename to crates/trippy/src/report/flows.rs diff --git a/src/report/json.rs b/crates/trippy/src/report/json.rs similarity index 96% rename from src/report/json.rs rename to crates/trippy/src/report/json.rs index 83e164c9..f0bb3685 100644 --- a/src/report/json.rs +++ b/crates/trippy/src/report/json.rs @@ -1,7 +1,7 @@ use crate::backend::trace::Trace; use crate::report::types::{Hop, Host, Info, Report}; use crate::TraceInfo; -use trippy::dns::Resolver; +use trippy_dns::Resolver; /// Generate a json report of trace data. pub fn report( diff --git a/src/report/silent.rs b/crates/trippy/src/report/silent.rs similarity index 100% rename from src/report/silent.rs rename to crates/trippy/src/report/silent.rs diff --git a/src/report/stream.rs b/crates/trippy/src/report/stream.rs similarity index 97% rename from src/report/stream.rs rename to crates/trippy/src/report/stream.rs index 94775824..6bb51fac 100644 --- a/src/report/stream.rs +++ b/crates/trippy/src/report/stream.rs @@ -3,7 +3,7 @@ use crate::report::types::Hop; use crate::TraceInfo; use anyhow::anyhow; use std::thread::sleep; -use trippy::dns::Resolver; +use trippy_dns::Resolver; /// Display a continuous stream of trace data. pub fn report(info: &TraceInfo, resolver: &R) -> anyhow::Result<()> { diff --git a/src/report/table.rs b/crates/trippy/src/report/table.rs similarity index 98% rename from src/report/table.rs rename to crates/trippy/src/report/table.rs index 139f36f2..0876a476 100644 --- a/src/report/table.rs +++ b/crates/trippy/src/report/table.rs @@ -3,7 +3,7 @@ use crate::TraceInfo; use comfy_table::presets::{ASCII_MARKDOWN, UTF8_FULL}; use comfy_table::{ContentArrangement, Table}; use itertools::Itertools; -use trippy::dns::Resolver; +use trippy_dns::Resolver; /// Generate a markdown table report of trace data. pub fn report_md( diff --git a/src/report/types.rs b/crates/trippy/src/report/types.rs similarity index 87% rename from src/report/types.rs rename to crates/trippy/src/report/types.rs index 0cb1a060..33f349ca 100644 --- a/src/report/types.rs +++ b/crates/trippy/src/report/types.rs @@ -3,7 +3,7 @@ use itertools::Itertools; use serde::{Serialize, Serializer}; use std::fmt::{Display, Formatter}; use std::net::IpAddr; -use trippy::dns::Resolver; +use trippy_dns::Resolver; #[derive(Serialize)] pub struct Report { @@ -109,8 +109,8 @@ pub struct Extensions { pub extensions: Vec, } -impl From<&trippy::tracing::Extensions> for Extensions { - fn from(value: &trippy::tracing::Extensions) -> Self { +impl From<&trippy_core::Extensions> for Extensions { + fn from(value: &trippy_core::Extensions) -> Self { Self { extensions: value .extensions @@ -136,13 +136,13 @@ pub enum Extension { Mpls(MplsLabelStack), } -impl From for Extension { - fn from(value: trippy::tracing::Extension) -> Self { +impl From for Extension { + fn from(value: trippy_core::Extension) -> Self { match value { - trippy::tracing::Extension::Unknown(unknown) => { + trippy_core::Extension::Unknown(unknown) => { Self::Unknown(UnknownExtension::from(unknown)) } - trippy::tracing::Extension::Mpls(mpls) => Self::Mpls(MplsLabelStack::from(mpls)), + trippy_core::Extension::Mpls(mpls) => Self::Mpls(MplsLabelStack::from(mpls)), } } } @@ -161,8 +161,8 @@ pub struct MplsLabelStack { pub members: Vec, } -impl From for MplsLabelStack { - fn from(value: trippy::tracing::MplsLabelStack) -> Self { +impl From for MplsLabelStack { + fn from(value: trippy_core::MplsLabelStack) -> Self { Self { members: value .members @@ -187,8 +187,8 @@ pub struct MplsLabelStackMember { pub ttl: u8, } -impl From for MplsLabelStackMember { - fn from(value: trippy::tracing::MplsLabelStackMember) -> Self { +impl From for MplsLabelStackMember { + fn from(value: trippy_core::MplsLabelStackMember) -> Self { Self { label: value.label, exp: value.exp, @@ -211,8 +211,8 @@ pub struct UnknownExtension { pub bytes: Vec, } -impl From for UnknownExtension { - fn from(value: trippy::tracing::UnknownExtension) -> Self { +impl From for UnknownExtension { + fn from(value: trippy_core::UnknownExtension) -> Self { Self { class_num: value.class_num, class_subtype: value.class_subtype, diff --git a/test_resources/backend/ipv4_3probes_3hops_completed.yaml b/crates/trippy/test_resources/backend/ipv4_3probes_3hops_completed.yaml similarity index 100% rename from test_resources/backend/ipv4_3probes_3hops_completed.yaml rename to crates/trippy/test_resources/backend/ipv4_3probes_3hops_completed.yaml diff --git a/test_resources/backend/ipv4_3probes_3hops_mixed_multi.yaml b/crates/trippy/test_resources/backend/ipv4_3probes_3hops_mixed_multi.yaml similarity index 100% rename from test_resources/backend/ipv4_3probes_3hops_mixed_multi.yaml rename to crates/trippy/test_resources/backend/ipv4_3probes_3hops_mixed_multi.yaml diff --git a/test_resources/backend/ipv4_4probes_0latency.yaml b/crates/trippy/test_resources/backend/ipv4_4probes_0latency.yaml similarity index 100% rename from test_resources/backend/ipv4_4probes_0latency.yaml rename to crates/trippy/test_resources/backend/ipv4_4probes_0latency.yaml diff --git a/test_resources/backend/ipv4_4probes_all_status.yaml b/crates/trippy/test_resources/backend/ipv4_4probes_all_status.yaml similarity index 100% rename from test_resources/backend/ipv4_4probes_all_status.yaml rename to crates/trippy/test_resources/backend/ipv4_4probes_all_status.yaml diff --git a/test_resources/config/completions_bash.txt b/crates/trippy/test_resources/config/completions_bash.txt similarity index 100% rename from test_resources/config/completions_bash.txt rename to crates/trippy/test_resources/config/completions_bash.txt diff --git a/test_resources/config/completions_elvish.txt b/crates/trippy/test_resources/config/completions_elvish.txt similarity index 100% rename from test_resources/config/completions_elvish.txt rename to crates/trippy/test_resources/config/completions_elvish.txt diff --git a/test_resources/config/completions_fish.txt b/crates/trippy/test_resources/config/completions_fish.txt similarity index 100% rename from test_resources/config/completions_fish.txt rename to crates/trippy/test_resources/config/completions_fish.txt diff --git a/test_resources/config/completions_powershell.txt b/crates/trippy/test_resources/config/completions_powershell.txt similarity index 100% rename from test_resources/config/completions_powershell.txt rename to crates/trippy/test_resources/config/completions_powershell.txt diff --git a/test_resources/config/completions_zsh.txt b/crates/trippy/test_resources/config/completions_zsh.txt similarity index 100% rename from test_resources/config/completions_zsh.txt rename to crates/trippy/test_resources/config/completions_zsh.txt diff --git a/test_resources/config/trip.1 b/crates/trippy/test_resources/config/trip.1 similarity index 100% rename from test_resources/config/trip.1 rename to crates/trippy/test_resources/config/trip.1 diff --git a/test_resources/config/usage_long.txt b/crates/trippy/test_resources/config/usage_long.txt similarity index 100% rename from test_resources/config/usage_long.txt rename to crates/trippy/test_resources/config/usage_long.txt diff --git a/test_resources/config/usage_short.txt b/crates/trippy/test_resources/config/usage_short.txt similarity index 100% rename from test_resources/config/usage_short.txt rename to crates/trippy/test_resources/config/usage_short.txt diff --git a/test_resources/tui/tui_binding_commands.txt b/crates/trippy/test_resources/tui/tui_binding_commands.txt similarity index 100% rename from test_resources/tui/tui_binding_commands.txt rename to crates/trippy/test_resources/tui/tui_binding_commands.txt diff --git a/test_resources/tui/tui_theme_items.txt b/crates/trippy/test_resources/tui/tui_theme_items.txt similarity index 100% rename from test_resources/tui/tui_theme_items.txt rename to crates/trippy/test_resources/tui/tui_theme_items.txt diff --git a/src/dns.rs b/src/dns.rs deleted file mode 100644 index 8c59773e..00000000 --- a/src/dns.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! A lazy DNS resolver. -//! -//! This module provides a cheaply cloneable, non-blocking, caching, forward -//! and reverse DNS resolver which support the ability to lookup Autonomous -//! System (AS) information. - -mod lazy_resolver; -mod resolver; - -pub use lazy_resolver::{Config, DnsResolver, IpAddrFamily, ResolveMethod}; -pub use resolver::{AsInfo, DnsEntry, Error, Resolved, Resolver, Result, Unresolved}; diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 45d32763..00000000 --- a/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![doc = include_str!("../README.md")] -#![warn(clippy::all, clippy::pedantic, clippy::nursery, rust_2018_idioms)] -#![allow( - clippy::module_name_repetitions, - clippy::struct_field_names, - clippy::option_if_let_else, - clippy::missing_const_for_fn, - clippy::cast_possible_truncation, - clippy::missing_errors_doc -)] -#![deny(unsafe_code)] - -pub mod tracing; - -pub mod dns; diff --git a/src/tracing.rs b/src/tracing.rs deleted file mode 100644 index 43b4ee33..00000000 --- a/src/tracing.rs +++ /dev/null @@ -1,29 +0,0 @@ -mod builder; -mod config; -mod constants; -mod error; -mod net; -mod probe; -mod tracer; -mod types; - -/// Packet wire formats. -pub mod packet; - -pub use builder::Builder; -pub use config::{ - defaults, ChannelConfig, ChannelConfigBuilder, Config, ConfigBuilder, IcmpExtensionParseMode, - MultipathStrategy, PortDirection, PrivilegeMode, Protocol, -}; -pub use net::channel::TracerChannel; -pub use net::source::SourceAddr; -pub use net::{PlatformImpl, SocketImpl}; -pub use probe::{ - Extension, Extensions, IcmpPacketType, MplsLabelStack, MplsLabelStackMember, Probe, - ProbeComplete, ProbeState, UnknownExtension, -}; -pub use tracer::{CompletionReason, Tracer, TracerRound}; -pub use types::{ - Flags, MaxInflight, MaxRounds, PacketSize, PayloadPattern, Port, Round, Sequence, TimeToLive, - TraceId, TypeOfService, -};