netlink-packet-wireguard-0.2.3/.cargo_vcs_info.json0000644000000001360000000000100157360ustar { "git": { "sha1": "c25e3bf2609e44d8f1a00fdf84a80b4481afc803" }, "path_in_vcs": "" }netlink-packet-wireguard-0.2.3/.github/workflows/clippy-rustfmt.yml000064400000000000000000000011021046102023000236420ustar 00000000000000name: Rustfmt and clippy check on: pull_request: types: [opened, synchronize, reopened] push: branches: - main jobs: rustfmt_clippy: strategy: fail-fast: true name: Rustfmt and clippy check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Rust Nightly run: | rustup override set nightly rustup update nightly rustup component add rustfmt clippy - name: rustfmt run: cargo fmt --all -- --check - name: clippy run: cargo clippy netlink-packet-wireguard-0.2.3/.github/workflows/license.yml000064400000000000000000000005201046102023000222650ustar 00000000000000name: license on: pull_request: types: [opened, synchronize, reopened] push: branches: - main jobs: check-license: name: Check License runs-on: ubuntu-latest timeout-minutes: 3 steps: - uses: actions/checkout@v3 - name: Check License Header uses: apache/skywalking-eyes@v0.3.0 netlink-packet-wireguard-0.2.3/.github/workflows/main.yml000064400000000000000000000013721046102023000215750ustar 00000000000000name: CI on: pull_request: types: [opened, synchronize, reopened] push: branches: - main jobs: ci: name: CI (stable) runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Rust Stable run: | rustup override set stable rustup update stable rustup component add llvm-tools-preview - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov - name: Test and Generate code coverage run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: files: lcov.info fail_ci_if_error: true netlink-packet-wireguard-0.2.3/.gitignore000064400000000000000000000000411046102023000165110ustar 00000000000000Cargo.lock target vendor/ *.swp netlink-packet-wireguard-0.2.3/.licenserc.yaml000064400000000000000000000003711046102023000174400ustar 00000000000000header: license: content: | SPDX-License-Identifier: MIT paths-ignore: - 'target' - '**/*.toml' - '**/*.lock' - '**/*.yml' - '**/*.md' - 'CHANGELOG' - 'LICENSE-MIT' - '.gitignore' comment: on-failure netlink-packet-wireguard-0.2.3/.rustfmt.toml000064400000000000000000000001141046102023000172010ustar 00000000000000max_width = 80 wrap_comments = true reorder_imports = true edition = "2021" netlink-packet-wireguard-0.2.3/CHANGELOG000064400000000000000000000001571046102023000157430ustar 00000000000000# Changelog ## [0.2.3] - 2023-07-10 ### Breaking changes - N/A ### New features - N/A ### Bug fixes - N/A netlink-packet-wireguard-0.2.3/Cargo.lock0000644000000426100000000000100137140ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] [[package]] name = "anyhow" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "env_logger" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "humantime", "is-terminal", "log", "regex", "termcolor", ] [[package]] name = "errno" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", "windows-sys", ] [[package]] name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", "libc", ] [[package]] name = "futures" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "genetlink" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f890076c1faa1298bf747ce3694a8d9e0d2cc4b06fe293f12dd95742bfd079f" dependencies = [ "futures", "log", "netlink-packet-core", "netlink-packet-generic", "netlink-packet-utils", "netlink-proto", "thiserror", "tokio", ] [[package]] name = "gimli" version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "hermit-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "is-terminal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", "windows-sys", ] [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "log" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "mio" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi", "windows-sys", ] [[package]] name = "netlink-packet-core" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" dependencies = [ "anyhow", "byteorder", "netlink-packet-utils", ] [[package]] name = "netlink-packet-generic" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd7eb8ad331c84c6b8cb7f685b448133e5ad82e1ffd5acafac374af4a5a308b" dependencies = [ "anyhow", "byteorder", "netlink-packet-core", "netlink-packet-utils", ] [[package]] name = "netlink-packet-utils" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" dependencies = [ "anyhow", "byteorder", "paste", "thiserror", ] [[package]] name = "netlink-packet-wireguard" version = "0.2.3" dependencies = [ "anyhow", "base64", "byteorder", "env_logger", "futures", "genetlink", "libc", "log", "netlink-packet-core", "netlink-packet-generic", "netlink-packet-utils", "netlink-proto", "tokio", ] [[package]] name = "netlink-proto" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "842c6770fc4bb33dd902f41829c61ef872b8e38de1405aa0b938b27b8fba12c3" dependencies = [ "bytes", "futures", "log", "netlink-packet-core", "netlink-sys", "thiserror", "tokio", ] [[package]] name = "netlink-sys" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "bytes", "futures", "libc", "log", "tokio", ] [[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "object" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] [[package]] name = "paste" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" [[package]] name = "pin-project-lite" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" version = "0.38.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "slab" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] [[package]] name = "socket2" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi", ] [[package]] name = "syn" version = "2.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "termcolor" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio" version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", "socket2", "tokio-macros", "windows-sys", ] [[package]] name = "tokio-macros" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "unicode-ident" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" netlink-packet-wireguard-0.2.3/Cargo.toml0000644000000031010000000000100137270ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "netlink-packet-wireguard" version = "0.2.3" authors = [ "Leo ", "Jake McGinty ", ] description = "Wireguard generic netlink packet definitions" homepage = "https://github.com/rust-netlink/netlink-packet-wireguard" readme = "README.md" keywords = [ "wireguard", "netlink", "linux", ] license = "MIT" repository = "https://github.com/rust-netlink/netlink-packet-wireguard" [dependencies.anyhow] version = "1.0.42" [dependencies.byteorder] version = "1.4.3" [dependencies.libc] version = "0.2.98" [dependencies.log] version = "0.4.14" [dependencies.netlink-packet-generic] version = "0.3.3" [dependencies.netlink-packet-utils] version = "0.5.2" [dev-dependencies.base64] version = "0.13.0" [dev-dependencies.env_logger] version = "0.10.0" [dev-dependencies.futures] version = "0.3.16" [dev-dependencies.genetlink] version = "0.2.5" [dev-dependencies.netlink-packet-core] version = "0.7.0" [dev-dependencies.netlink-proto] version = "0.11.2" [dev-dependencies.tokio] version = "1.9.0" features = [ "macros", "rt-multi-thread", ] netlink-packet-wireguard-0.2.3/Cargo.toml.orig000064400000000000000000000015561046102023000174240ustar 00000000000000[package] name = "netlink-packet-wireguard" version = "0.2.3" authors = ["Leo ", "Jake McGinty "] edition = "2018" homepage = "https://github.com/rust-netlink/netlink-packet-wireguard" repository = "https://github.com/rust-netlink/netlink-packet-wireguard" keywords = ["wireguard", "netlink", "linux"] license = "MIT" readme = "README.md" description = "Wireguard generic netlink packet definitions" [dependencies] anyhow = "1.0.42" byteorder = "1.4.3" libc = "0.2.98" log = "0.4.14" netlink-packet-generic = { version = "0.3.3" } netlink-packet-utils = { version = "0.5.2" } [dev-dependencies] base64 = "0.13.0" env_logger = "0.10.0" futures = "0.3.16" netlink-packet-core = { version = "0.7.0" } netlink-proto = { version = "0.11.2" } genetlink = { version = "0.2.5" } tokio = { version = "1.9.0", features = ["macros", "rt-multi-thread"] } netlink-packet-wireguard-0.2.3/README.md000064400000000000000000000001331046102023000160020ustar 00000000000000# netlink-packet-wireguard A Rust crate for wireguard generic netlink packet definitions. netlink-packet-wireguard-0.2.3/examples/get_wireguard_info.rs000064400000000000000000000071141046102023000225600ustar 00000000000000// SPDX-License-Identifier: MIT use futures::StreamExt; use genetlink::new_connection; use netlink_packet_core::{ NetlinkMessage, NetlinkPayload, NLM_F_DUMP, NLM_F_REQUEST, }; use netlink_packet_generic::GenlMessage; use netlink_packet_wireguard::{ nlas::{WgAllowedIpAttrs, WgDeviceAttrs, WgPeerAttrs}, Wireguard, WireguardCmd, }; use std::env::args; #[tokio::main] async fn main() { env_logger::init(); let argv: Vec = args().collect(); if argv.len() < 2 { eprintln!("Usage: get_wireguard_info "); return; } let (connection, mut handle, _) = new_connection().unwrap(); tokio::spawn(connection); let genlmsg: GenlMessage = GenlMessage::from_payload(Wireguard { cmd: WireguardCmd::GetDevice, nlas: vec![WgDeviceAttrs::IfName(argv[1].clone())], }); let mut nlmsg = NetlinkMessage::from(genlmsg); nlmsg.header.flags = NLM_F_REQUEST | NLM_F_DUMP; let mut res = handle.request(nlmsg).await.unwrap(); while let Some(result) = res.next().await { let rx_packet = result.unwrap(); match rx_packet.payload { NetlinkPayload::InnerMessage(genlmsg) => { print_wg_payload(genlmsg.payload); } NetlinkPayload::Error(e) => { eprintln!("Error: {:?}", e.to_io()); } _ => (), }; } } fn print_wg_payload(wg: Wireguard) { for nla in &wg.nlas { match nla { WgDeviceAttrs::IfIndex(v) => println!("IfIndex: {}", v), WgDeviceAttrs::IfName(v) => println!("IfName: {}", v), WgDeviceAttrs::PrivateKey(_) => println!("PrivateKey: (hidden)"), WgDeviceAttrs::PublicKey(v) => { println!("PublicKey: {}", base64::encode(v)) } WgDeviceAttrs::ListenPort(v) => println!("ListenPort: {}", v), WgDeviceAttrs::Fwmark(v) => println!("Fwmark: {}", v), WgDeviceAttrs::Peers(nlas) => { for peer in nlas { println!("Peer: "); print_wg_peer(peer); } } _ => (), } } } fn print_wg_peer(nlas: &[WgPeerAttrs]) { for nla in nlas { match nla { WgPeerAttrs::PublicKey(v) => { println!(" PublicKey: {}", base64::encode(v)) } WgPeerAttrs::PresharedKey(_) => { println!(" PresharedKey: (hidden)") } WgPeerAttrs::Endpoint(v) => println!(" Endpoint: {}", v), WgPeerAttrs::PersistentKeepalive(v) => { println!(" PersistentKeepalive: {}", v) } WgPeerAttrs::LastHandshake(v) => { println!(" LastHandshake: {:?}", v) } WgPeerAttrs::RxBytes(v) => println!(" RxBytes: {}", v), WgPeerAttrs::TxBytes(v) => println!(" TxBytes: {}", v), WgPeerAttrs::AllowedIps(nlas) => { for ip in nlas { print_wg_allowedip(ip); } } _ => (), } } } fn print_wg_allowedip(nlas: &[WgAllowedIpAttrs]) -> Option<()> { let ipaddr = nlas.iter().find_map(|nla| { if let WgAllowedIpAttrs::IpAddr(addr) = nla { Some(*addr) } else { None } })?; let cidr = nlas.iter().find_map(|nla| { if let WgAllowedIpAttrs::Cidr(cidr) = nla { Some(*cidr) } else { None } })?; println!(" AllowedIp: {}/{}", ipaddr, cidr); Some(()) } netlink-packet-wireguard-0.2.3/src/constants.rs000064400000000000000000000026161046102023000177040ustar 00000000000000// SPDX-License-Identifier: MIT pub const AF_INET: u16 = libc::AF_INET as u16; pub const AF_INET6: u16 = libc::AF_INET6 as u16; pub const WG_KEY_LEN: usize = 32; pub const WG_CMD_GET_DEVICE: u8 = 0; pub const WG_CMD_SET_DEVICE: u8 = 1; pub const WGDEVICE_F_REPLACE_PEERS: u32 = 1 << 0; pub const WGDEVICE_A_UNSPEC: u16 = 0; pub const WGDEVICE_A_IFINDEX: u16 = 1; pub const WGDEVICE_A_IFNAME: u16 = 2; pub const WGDEVICE_A_PRIVATE_KEY: u16 = 3; pub const WGDEVICE_A_PUBLIC_KEY: u16 = 4; pub const WGDEVICE_A_FLAGS: u16 = 5; pub const WGDEVICE_A_LISTEN_PORT: u16 = 6; pub const WGDEVICE_A_FWMARK: u16 = 7; pub const WGDEVICE_A_PEERS: u16 = 8; pub const WGPEER_F_REMOVE_ME: u32 = 1 << 0; pub const WGPEER_F_REPLACE_ALLOWEDIPS: u32 = 1 << 1; pub const WGPEER_F_UPDATE_ONLY: u32 = 1 << 2; pub const WGPEER_A_UNSPEC: u16 = 0; pub const WGPEER_A_PUBLIC_KEY: u16 = 1; pub const WGPEER_A_PRESHARED_KEY: u16 = 2; pub const WGPEER_A_FLAGS: u16 = 3; pub const WGPEER_A_ENDPOINT: u16 = 4; pub const WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: u16 = 5; pub const WGPEER_A_LAST_HANDSHAKE_TIME: u16 = 6; pub const WGPEER_A_RX_BYTES: u16 = 7; pub const WGPEER_A_TX_BYTES: u16 = 8; pub const WGPEER_A_ALLOWEDIPS: u16 = 9; pub const WGPEER_A_PROTOCOL_VERSION: u16 = 10; pub const WGALLOWEDIP_A_UNSPEC: u16 = 0; pub const WGALLOWEDIP_A_FAMILY: u16 = 1; pub const WGALLOWEDIP_A_IPADDR: u16 = 2; pub const WGALLOWEDIP_A_CIDR_MASK: u16 = 3; netlink-packet-wireguard-0.2.3/src/lib.rs000064400000000000000000000124471046102023000164410ustar 00000000000000// SPDX-License-Identifier: MIT #[macro_use] extern crate log; use crate::constants::*; use anyhow::Context; use netlink_packet_generic::{GenlFamily, GenlHeader}; use netlink_packet_utils::{nla::NlasIterator, traits::*, DecodeError}; use nlas::WgDeviceAttrs; use std::convert::{TryFrom, TryInto}; pub mod constants; pub mod nlas; mod raw; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum WireguardCmd { GetDevice, SetDevice, } impl From for u8 { fn from(cmd: WireguardCmd) -> Self { use WireguardCmd::*; match cmd { GetDevice => WG_CMD_GET_DEVICE, SetDevice => WG_CMD_SET_DEVICE, } } } impl TryFrom for WireguardCmd { type Error = DecodeError; fn try_from(value: u8) -> Result { use WireguardCmd::*; Ok(match value { WG_CMD_GET_DEVICE => GetDevice, WG_CMD_SET_DEVICE => SetDevice, cmd => { return Err(DecodeError::from(format!( "Unknown wireguard command: {}", cmd ))) } }) } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Wireguard { pub cmd: WireguardCmd, pub nlas: Vec, } impl GenlFamily for Wireguard { fn family_name() -> &'static str { "wireguard" } fn version(&self) -> u8 { 1 } fn command(&self) -> u8 { self.cmd.into() } } impl Emitable for Wireguard { fn emit(&self, buffer: &mut [u8]) { self.nlas.as_slice().emit(buffer) } fn buffer_len(&self) -> usize { self.nlas.as_slice().buffer_len() } } impl ParseableParametrized<[u8], GenlHeader> for Wireguard { fn parse_with_param( buf: &[u8], header: GenlHeader, ) -> Result { Ok(Self { cmd: header.cmd.try_into()?, nlas: parse_nlas(buf)?, }) } } fn parse_nlas(buf: &[u8]) -> Result, DecodeError> { let mut nlas = Vec::new(); let error_msg = "failed to parse message attributes"; for nla in NlasIterator::new(buf) { let nla = &nla.context(error_msg)?; let parsed = WgDeviceAttrs::parse(nla).context(error_msg)?; nlas.push(parsed); } Ok(nlas) } #[cfg(test)] mod test { use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST}; use netlink_packet_generic::GenlMessage; use crate::nlas::{WgAllowedIp, WgAllowedIpAttrs, WgPeer, WgPeerAttrs}; use super::*; const KNOWN_VALID_PACKET: &[u8] = &[ 0x74, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, 0x38, 0x24, 0xd6, 0x61, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x66, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x00, 0x00, 0x54, 0x00, 0x08, 0x80, 0x50, 0x00, 0x00, 0x80, 0x24, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x09, 0x80, 0x1c, 0x00, 0x00, 0x80, 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x05, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, ]; #[test] fn test_parse_known_valid_packet() { NetlinkMessage::>::deserialize( KNOWN_VALID_PACKET, ) .unwrap(); } #[test] fn test_serialize_then_deserialize() { let genlmsg: GenlMessage = GenlMessage::from_payload(Wireguard { cmd: WireguardCmd::SetDevice, nlas: vec![ WgDeviceAttrs::IfName("wg0".to_string()), WgDeviceAttrs::PrivateKey([0xaa; 32]), WgDeviceAttrs::Peers(vec![ WgPeer(vec![ WgPeerAttrs::PublicKey([0x01; 32]), WgPeerAttrs::PresharedKey([0x01; 32]), WgPeerAttrs::AllowedIps(vec![WgAllowedIp(vec![ WgAllowedIpAttrs::IpAddr([10, 0, 0, 0].into()), WgAllowedIpAttrs::Cidr(24), WgAllowedIpAttrs::Family(AF_INET), ])]), ]), WgPeer(vec![ WgPeerAttrs::PublicKey([0x02; 32]), WgPeerAttrs::PresharedKey([0x01; 32]), WgPeerAttrs::AllowedIps(vec![WgAllowedIp(vec![ WgAllowedIpAttrs::IpAddr([10, 0, 1, 0].into()), WgAllowedIpAttrs::Cidr(24), WgAllowedIpAttrs::Family(AF_INET), ])]), ]), ]), ], }); let mut nlmsg = NetlinkMessage::from(genlmsg); nlmsg.header.flags = NLM_F_REQUEST | NLM_F_ACK; nlmsg.finalize(); let mut buf = [0; 4096]; nlmsg.serialize(&mut buf); let len = nlmsg.buffer_len(); NetlinkMessage::>::deserialize(&buf[..len]) .unwrap(); } } netlink-packet-wireguard-0.2.3/src/nlas/allowedip.rs000064400000000000000000000046661046102023000206140ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{ constants::*, raw::{emit_ip, parse_ip, IPV4_LEN, IPV6_LEN}, }; use anyhow::Context; use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{Nla, NlaBuffer}, parsers::*, traits::*, DecodeError, }; use std::{mem::size_of_val, net::IpAddr}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum WgAllowedIpAttrs { Unspec(Vec), Family(u16), IpAddr(IpAddr), Cidr(u8), } impl Nla for WgAllowedIpAttrs { fn value_len(&self) -> usize { match self { WgAllowedIpAttrs::Unspec(bytes) => bytes.len(), WgAllowedIpAttrs::Family(v) => size_of_val(v), WgAllowedIpAttrs::IpAddr(v) => match *v { IpAddr::V4(_) => IPV4_LEN, IpAddr::V6(_) => IPV6_LEN, }, WgAllowedIpAttrs::Cidr(v) => size_of_val(v), } } fn kind(&self) -> u16 { match self { WgAllowedIpAttrs::Unspec(_) => WGALLOWEDIP_A_UNSPEC, WgAllowedIpAttrs::Family(_) => WGALLOWEDIP_A_FAMILY, WgAllowedIpAttrs::IpAddr(_) => WGALLOWEDIP_A_IPADDR, WgAllowedIpAttrs::Cidr(_) => WGALLOWEDIP_A_CIDR_MASK, } } fn emit_value(&self, buffer: &mut [u8]) { match self { WgAllowedIpAttrs::Unspec(bytes) => buffer.copy_from_slice(bytes), WgAllowedIpAttrs::Family(v) => NativeEndian::write_u16(buffer, *v), WgAllowedIpAttrs::IpAddr(v) => emit_ip(v, buffer), WgAllowedIpAttrs::Cidr(v) => buffer[0] = *v, } } } impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for WgAllowedIpAttrs { fn parse(buf: &NlaBuffer<&'a T>) -> Result { let payload = buf.value(); Ok(match buf.kind() { WGALLOWEDIP_A_UNSPEC => Self::Unspec(payload.to_vec()), WGALLOWEDIP_A_FAMILY => Self::Family( parse_u16(payload) .context("invalid WGALLOWEDIP_A_FAMILY value")?, ), WGALLOWEDIP_A_IPADDR => Self::IpAddr( parse_ip(payload) .context("invalid WGALLOWEDIP_A_IPADDR value")?, ), WGALLOWEDIP_A_CIDR_MASK => Self::Cidr(payload[0]), kind => { return Err(DecodeError::from(format!( "invalid NLA kind: {}", kind ))) } }) } } netlink-packet-wireguard-0.2.3/src/nlas/device.rs000064400000000000000000000124501046102023000200610ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{ constants::*, nlas::{WgPeer, WgPeerAttrs}, }; use anyhow::Context; use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{Nla, NlaBuffer, NlasIterator}, parsers::*, traits::*, DecodeError, }; use std::{convert::TryInto, mem::size_of_val}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum WgDeviceAttrs { Unspec(Vec), IfIndex(u32), IfName(String), PrivateKey([u8; WG_KEY_LEN]), PublicKey([u8; WG_KEY_LEN]), ListenPort(u16), Fwmark(u32), Peers(Vec), Flags(u32), } impl Nla for WgDeviceAttrs { fn value_len(&self) -> usize { match self { WgDeviceAttrs::Unspec(bytes) => bytes.len(), WgDeviceAttrs::IfIndex(v) => size_of_val(v), WgDeviceAttrs::IfName(v) => v.as_bytes().len() + 1, WgDeviceAttrs::PrivateKey(v) => size_of_val(v), WgDeviceAttrs::PublicKey(v) => size_of_val(v), WgDeviceAttrs::ListenPort(v) => size_of_val(v), WgDeviceAttrs::Fwmark(v) => size_of_val(v), WgDeviceAttrs::Peers(nlas) => { nlas.iter().map(|op| op.buffer_len()).sum() } WgDeviceAttrs::Flags(v) => size_of_val(v), } } fn kind(&self) -> u16 { match self { WgDeviceAttrs::Unspec(_) => WGDEVICE_A_UNSPEC, WgDeviceAttrs::IfIndex(_) => WGDEVICE_A_IFINDEX, WgDeviceAttrs::IfName(_) => WGDEVICE_A_IFNAME, WgDeviceAttrs::PrivateKey(_) => WGDEVICE_A_PRIVATE_KEY, WgDeviceAttrs::PublicKey(_) => WGDEVICE_A_PUBLIC_KEY, WgDeviceAttrs::ListenPort(_) => WGDEVICE_A_LISTEN_PORT, WgDeviceAttrs::Fwmark(_) => WGDEVICE_A_FWMARK, WgDeviceAttrs::Peers(_) => WGDEVICE_A_PEERS, WgDeviceAttrs::Flags(_) => WGDEVICE_A_FLAGS, } } fn emit_value(&self, buffer: &mut [u8]) { match self { WgDeviceAttrs::Unspec(bytes) => buffer.copy_from_slice(bytes), WgDeviceAttrs::IfIndex(v) => NativeEndian::write_u32(buffer, *v), WgDeviceAttrs::IfName(s) => { buffer[..s.len()].copy_from_slice(s.as_bytes()); buffer[s.len()] = 0; } WgDeviceAttrs::PrivateKey(v) => buffer.copy_from_slice(v), WgDeviceAttrs::PublicKey(v) => buffer.copy_from_slice(v), WgDeviceAttrs::ListenPort(v) => NativeEndian::write_u16(buffer, *v), WgDeviceAttrs::Fwmark(v) => NativeEndian::write_u32(buffer, *v), WgDeviceAttrs::Peers(nlas) => { let mut len = 0; for op in nlas { op.emit(&mut buffer[len..]); len += op.buffer_len(); } } WgDeviceAttrs::Flags(v) => NativeEndian::write_u32(buffer, *v), } } fn is_nested(&self) -> bool { matches!(self, WgDeviceAttrs::Peers(_)) } } impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for WgDeviceAttrs { fn parse(buf: &NlaBuffer<&'a T>) -> Result { let payload = buf.value(); Ok(match buf.kind() { WGDEVICE_A_UNSPEC => Self::Unspec(payload.to_vec()), WGDEVICE_A_IFINDEX => Self::IfIndex( parse_u32(payload) .context("invalid WGDEVICE_A_IFINDEX value")?, ), WGDEVICE_A_IFNAME => Self::IfName( parse_string(payload) .context("invalid WGDEVICE_A_IFNAME value")?, ), WGDEVICE_A_PRIVATE_KEY => Self::PrivateKey( payload .try_into() .context("invalid WGDEVICE_A_PRIVATE_KEY value")?, ), WGDEVICE_A_PUBLIC_KEY => Self::PublicKey( payload .try_into() .context("invalid WGDEVICE_A_PUBLIC_KEY value")?, ), WGDEVICE_A_LISTEN_PORT => Self::ListenPort( parse_u16(payload) .context("invalid WGDEVICE_A_LISTEN_PORT value")?, ), WGDEVICE_A_FWMARK => Self::Fwmark( parse_u32(payload) .context("invalid WGDEVICE_A_FWMARK value")?, ), WGDEVICE_A_PEERS => { let error_msg = "failed to parse WGDEVICE_A_PEERS"; let mut peers = Vec::new(); for nlas in NlasIterator::new(payload) { let nlas = &nlas.context(error_msg)?; let mut group = Vec::new(); for nla in NlasIterator::new(nlas.value()) { let nla = &nla.context(error_msg)?; let parsed = WgPeerAttrs::parse(nla).context(error_msg)?; group.push(parsed); } peers.push(WgPeer(group)); } Self::Peers(peers) } WGDEVICE_A_FLAGS => Self::Flags( parse_u32(payload).context("invalid WGDEVICE_A_FLAGS value")?, ), kind => { return Err(DecodeError::from(format!( "invalid NLA kind: {}", kind ))) } }) } } netlink-packet-wireguard-0.2.3/src/nlas/mod.rs000064400000000000000000000002751046102023000174030ustar 00000000000000// SPDX-License-Identifier: MIT mod allowedip; mod device; mod peer; pub use allowedip::WgAllowedIpAttrs; pub use device::WgDeviceAttrs; pub use peer::{WgAllowedIp, WgPeer, WgPeerAttrs}; netlink-packet-wireguard-0.2.3/src/nlas/peer.rs000064400000000000000000000170071046102023000175600ustar 00000000000000// SPDX-License-Identifier: MIT use super::WgAllowedIpAttrs; use crate::{ constants::*, raw::{ emit_socket_addr, emit_timespec, parse_socket_addr, parse_timespec, SOCKET_ADDR_V4_LEN, SOCKET_ADDR_V6_LEN, TIMESPEC_LEN, }, }; use anyhow::Context; use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{Nla, NlaBuffer, NlasIterator}, parsers::*, traits::*, DecodeError, }; use std::{ convert::TryInto, mem::size_of_val, net::SocketAddr, ops::Deref, time::SystemTime, }; #[derive(Clone, Debug, PartialEq, Eq)] pub struct WgPeer(pub Vec); impl Nla for WgPeer { fn value_len(&self) -> usize { self.0.as_slice().buffer_len() } fn kind(&self) -> u16 { 0 } fn emit_value(&self, buffer: &mut [u8]) { self.0.as_slice().emit(buffer); } fn is_nested(&self) -> bool { true } } impl Deref for WgPeer { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct WgAllowedIp(pub Vec); impl Nla for WgAllowedIp { fn value_len(&self) -> usize { self.0.as_slice().buffer_len() } fn kind(&self) -> u16 { 0 } fn emit_value(&self, buffer: &mut [u8]) { self.0.as_slice().emit(buffer); } fn is_nested(&self) -> bool { true } } impl Deref for WgAllowedIp { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum WgPeerAttrs { Unspec(Vec), PublicKey([u8; WG_KEY_LEN]), PresharedKey([u8; WG_KEY_LEN]), Endpoint(SocketAddr), PersistentKeepalive(u16), LastHandshake(SystemTime), RxBytes(u64), TxBytes(u64), AllowedIps(Vec), ProtocolVersion(u32), Flags(u32), } impl Nla for WgPeerAttrs { fn value_len(&self) -> usize { match self { WgPeerAttrs::Unspec(bytes) => bytes.len(), WgPeerAttrs::PublicKey(v) => size_of_val(v), WgPeerAttrs::PresharedKey(v) => size_of_val(v), WgPeerAttrs::Endpoint(v) => match *v { SocketAddr::V4(_) => SOCKET_ADDR_V4_LEN, SocketAddr::V6(_) => SOCKET_ADDR_V6_LEN, }, WgPeerAttrs::PersistentKeepalive(v) => size_of_val(v), WgPeerAttrs::LastHandshake(_) => TIMESPEC_LEN, WgPeerAttrs::RxBytes(v) => size_of_val(v), WgPeerAttrs::TxBytes(v) => size_of_val(v), WgPeerAttrs::AllowedIps(nlas) => { nlas.iter().map(|op| op.buffer_len()).sum() } WgPeerAttrs::ProtocolVersion(v) => size_of_val(v), WgPeerAttrs::Flags(v) => size_of_val(v), } } fn kind(&self) -> u16 { match self { WgPeerAttrs::Unspec(_) => WGPEER_A_UNSPEC, WgPeerAttrs::PublicKey(_) => WGPEER_A_PUBLIC_KEY, WgPeerAttrs::PresharedKey(_) => WGPEER_A_PRESHARED_KEY, WgPeerAttrs::Endpoint(_) => WGPEER_A_ENDPOINT, WgPeerAttrs::PersistentKeepalive(_) => { WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL } WgPeerAttrs::LastHandshake(_) => WGPEER_A_LAST_HANDSHAKE_TIME, WgPeerAttrs::RxBytes(_) => WGPEER_A_RX_BYTES, WgPeerAttrs::TxBytes(_) => WGPEER_A_TX_BYTES, WgPeerAttrs::AllowedIps(_) => WGPEER_A_ALLOWEDIPS, WgPeerAttrs::ProtocolVersion(_) => WGPEER_A_PROTOCOL_VERSION, WgPeerAttrs::Flags(_) => WGPEER_A_FLAGS, } } fn emit_value(&self, buffer: &mut [u8]) { match self { WgPeerAttrs::Unspec(bytes) => buffer.copy_from_slice(bytes), WgPeerAttrs::PublicKey(v) => buffer.copy_from_slice(v), WgPeerAttrs::PresharedKey(v) => buffer.copy_from_slice(v), WgPeerAttrs::Endpoint(v) => emit_socket_addr(v, buffer), WgPeerAttrs::PersistentKeepalive(v) => { NativeEndian::write_u16(buffer, *v) } WgPeerAttrs::LastHandshake(v) => emit_timespec(v, buffer), WgPeerAttrs::RxBytes(v) => NativeEndian::write_u64(buffer, *v), WgPeerAttrs::TxBytes(v) => NativeEndian::write_u64(buffer, *v), WgPeerAttrs::AllowedIps(nlas) => { let mut len = 0; for op in nlas { op.emit(&mut buffer[len..]); len += op.buffer_len(); } } WgPeerAttrs::ProtocolVersion(v) => { NativeEndian::write_u32(buffer, *v) } WgPeerAttrs::Flags(v) => NativeEndian::write_u32(buffer, *v), } } fn is_nested(&self) -> bool { matches!(self, WgPeerAttrs::AllowedIps(_)) } } impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for WgPeerAttrs { fn parse(buf: &NlaBuffer<&'a T>) -> Result { let payload = buf.value(); Ok(match buf.kind() { WGPEER_A_UNSPEC => Self::Unspec(payload.to_vec()), WGPEER_A_PUBLIC_KEY => Self::PublicKey( payload.try_into().context("invalid WGPEER_A_PUBLIC_KEY")?, ), WGPEER_A_PRESHARED_KEY => Self::PresharedKey( payload .try_into() .context("invalid WGPEER_A_PRESHARED_KEY")?, ), WGPEER_A_ENDPOINT => Self::Endpoint( parse_socket_addr(payload) .context("invalid WGPEER_A_ENDPOINT")?, ), WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL => { Self::PersistentKeepalive(parse_u16(payload).context( "invalid WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL value", )?) } WGPEER_A_LAST_HANDSHAKE_TIME => Self::LastHandshake( parse_timespec(payload) .context("invalid WGPEER_A_LAST_HANDSHAKE_TIME")?, ), WGPEER_A_RX_BYTES => Self::RxBytes( parse_u64(payload) .context("invalid WGPEER_A_RX_BYTES value")?, ), WGPEER_A_TX_BYTES => Self::TxBytes( parse_u64(payload) .context("invalid WGPEER_A_TX_BYTES value")?, ), WGPEER_A_ALLOWEDIPS => { let error_msg = "failed to parse WGPEER_A_ALLOWEDIPS"; let mut ips = Vec::new(); for nlas in NlasIterator::new(payload) { let nlas = &nlas.context(error_msg)?; let mut group = Vec::new(); for nla in NlasIterator::new(nlas.value()) { let nla = &nla.context(error_msg)?; let parsed = WgAllowedIpAttrs::parse(nla).context(error_msg)?; group.push(parsed); } ips.push(WgAllowedIp(group)); } Self::AllowedIps(ips) } WGPEER_A_PROTOCOL_VERSION => Self::ProtocolVersion( parse_u32(payload) .context("invalid WGPEER_A_PROTOCOL_VERSION value")?, ), WGPEER_A_FLAGS => Self::Flags( parse_u32(payload).context("invalid WGPEER_A_FLAGS value")?, ), kind => { return Err(DecodeError::from(format!( "invalid NLA kind: {}", kind ))) } }) } } netlink-packet-wireguard-0.2.3/src/raw.rs000064400000000000000000000213511046102023000164560ustar 00000000000000// SPDX-License-Identifier: MIT use std::{ convert::TryFrom, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, time::{Duration, SystemTime}, }; use byteorder::{BigEndian, ByteOrder, NativeEndian}; use netlink_packet_utils::DecodeError; use crate::constants::{AF_INET, AF_INET6}; pub const IPV4_LEN: usize = 4; pub const IPV6_LEN: usize = 16; pub const SOCKET_ADDR_V4_LEN: usize = 16; pub const SOCKET_ADDR_V6_LEN: usize = 28; pub const TIMESPEC_LEN: usize = 16; /// Parse an IPv6 socket address, defined as: /// ```c /// struct sockaddr_in6 { /// sa_family_t sin6_family; /* AF_INET6 */ /// in_port_t sin6_port; /* port number */ /// uint32_t sin6_flowinfo; /* IPv6 flow information */ /// struct in6_addr sin6_addr; /* IPv6 address */ /// uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */ /// }; /// struct in6_addr { /// unsigned char s6_addr[16]; /* IPv6 address */ /// }; /// ``` /// `sockaddr_in6` is 4 bytes aligned (28 bytes) so there's no padding. fn parse_socket_addr_v6(payload: &[u8]) -> SocketAddrV6 { assert_eq!(payload.len(), SOCKET_ADDR_V6_LEN); // We don't need the address family to build a SocketAddrv6 // let address_family = NativeEndian::read_u16(&payload[..2]); let port = BigEndian::read_u16(&payload[2..4]); let flow_info = NativeEndian::read_u32(&payload[4..8]); // We know we have exactly 16 bytes so this won't fail let ip_bytes = <[u8; 16]>::try_from(&payload[8..24]).unwrap(); let ip = Ipv6Addr::from(ip_bytes); let scope_id = NativeEndian::read_u32(&payload[24..28]); SocketAddrV6::new(ip, port, flow_info, scope_id) } /// Parse an IPv4 socket address, defined as: /// ```c /// #if __UAPI_DEF_SOCKADDR_IN /// #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ /// struct sockaddr_in { /// __kernel_sa_family_t sin_family; /* Address family */ /// __be16 sin_port; /* Port number */ /// struct in_addr sin_addr; /* Internet address */ /// /* Pad to size of `struct sockaddr'. */ /// unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; /// }; fn parse_socket_addr_v4(payload: &[u8]) -> SocketAddrV4 { assert_eq!(payload.len(), 16); // We don't need the address family to build a SocketAddr4v // let address_family = NativeEndian::read_u16(&payload[..2]); let port = BigEndian::read_u16(&payload[2..4]); // We know we have exactly 4 bytes so this won't fail let ip_bytes = <[u8; 4]>::try_from(&payload[4..8]).unwrap(); let ip = Ipv4Addr::from(ip_bytes); SocketAddrV4::new(ip, port) } pub fn parse_ip(payload: &[u8]) -> Result { match payload.len() { IPV4_LEN => { // This won't fail since we ensure the slice is 4 bytes long let ip_bytes = <[u8; IPV4_LEN]>::try_from(payload).unwrap(); Ok(IpAddr::V4(Ipv4Addr::from(ip_bytes))) } IPV6_LEN => { // This won't fail since we ensure the slice is 16 bytes long let ip_bytes = <[u8; IPV6_LEN]>::try_from(payload).unwrap(); Ok(IpAddr::V6(Ipv6Addr::from(ip_bytes))) } _ => Err(DecodeError::from(format!( "invalid IP address: {:x?}", payload ))), } } pub fn emit_ip(addr: &IpAddr, buf: &mut [u8]) { match addr { IpAddr::V4(ip) => { buf[..IPV4_LEN].copy_from_slice(ip.octets().as_slice()); } IpAddr::V6(ip) => { buf[..IPV6_LEN].copy_from_slice(ip.octets().as_slice()); } } } /// Emit an IPv4 socket address in the given buffer. An IPv4 socket /// address is defined as: /// ```c /// #if __UAPI_DEF_SOCKADDR_IN /// #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ /// struct sockaddr_in { /// __kernel_sa_family_t sin_family; /* Address family */ /// __be16 sin_port; /* Port number */ /// struct in_addr sin_addr; /* Internet address */ /// /* Pad to size of `struct sockaddr'. */ /// unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; /// }; /// ``` /// Note that this adds 8 bytes of padding so the buffer must be large /// enough to account for them. fn emit_socket_addr_v4(addr: &SocketAddrV4, buf: &mut [u8]) { NativeEndian::write_u16(&mut buf[..2], AF_INET); BigEndian::write_u16(&mut buf[2..4], addr.port()); buf[4..8].copy_from_slice(addr.ip().octets().as_slice()); // padding buf[8..16].copy_from_slice([0; 8].as_slice()); } /// Emit an IPv6 socket address. /// /// An IPv6 socket address is defined as: /// ```c /// struct sockaddr_in6 { /// sa_family_t sin6_family; /* AF_INET6 */ /// in_port_t sin6_port; /* port number */ /// uint32_t sin6_flowinfo; /* IPv6 flow information */ /// struct in6_addr sin6_addr; /* IPv6 address */ /// uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */ /// }; /// struct in6_addr { /// unsigned char s6_addr[16]; /* IPv6 address */ /// }; /// ``` /// `sockaddr_in6` is 4 bytes aligned (28 bytes) so there's no padding. fn emit_socket_addr_v6(addr: &SocketAddrV6, buf: &mut [u8]) { NativeEndian::write_u16(&mut buf[..2], AF_INET6); BigEndian::write_u16(&mut buf[2..4], addr.port()); NativeEndian::write_u32(&mut buf[4..8], addr.flowinfo()); buf[8..24].copy_from_slice(addr.ip().octets().as_slice()); NativeEndian::write_u32(&mut buf[24..28], addr.scope_id()); } pub fn emit_socket_addr(addr: &SocketAddr, buf: &mut [u8]) { match addr { SocketAddr::V4(v4) => emit_socket_addr_v4(v4, buf), SocketAddr::V6(v6) => emit_socket_addr_v6(v6, buf), } } pub fn parse_socket_addr(buf: &[u8]) -> Result { match buf.len() { SOCKET_ADDR_V4_LEN => Ok(SocketAddr::V4(parse_socket_addr_v4(buf))), SOCKET_ADDR_V6_LEN => Ok(SocketAddr::V6(parse_socket_addr_v6(buf))), _ => Err(format!( "invalid socket address (should be 16 or 28 bytes): {:x?}", buf ) .into()), } } pub fn emit_timespec(time: &SystemTime, buf: &mut [u8]) { match time.duration_since(SystemTime::UNIX_EPOCH) { Ok(epoch_elapsed) => { NativeEndian::write_i64( &mut buf[..8], epoch_elapsed.as_secs() as i64, ); NativeEndian::write_i64( &mut buf[8..16], epoch_elapsed.subsec_nanos() as i64, ); } Err(e) => { // This method is supposed to not fail so just log an // error. If we want such errors to be handled by the // caller, we shouldn't use `SystemTime`. error!("error while emitting timespec: {:?}", e); NativeEndian::write_i64(&mut buf[..8], 0_i64); NativeEndian::write_i64(&mut buf[8..16], 0_i64); } } } pub fn parse_timespec(buf: &[u8]) -> Result { if buf.len() != TIMESPEC_LEN { return Err(DecodeError::from(format!( "Invalid timespec buffer: {:x?}", buf ))); } let epoch_elapsed_s = Duration::from_secs(NativeEndian::read_u64(&buf[..8])); let epoch_elapsed_ns = Duration::from_nanos(NativeEndian::read_u64(&buf[8..16])); Ok(SystemTime::UNIX_EPOCH + epoch_elapsed_s + epoch_elapsed_ns) } #[cfg(test)] mod test { use std::str::FromStr; use super::*; const SOCKADDR_IN_BYTES_1: &[u8] = b"\x02\x00\x1c\x7a\x7f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"; // 127.0.0.1:7290 const SOCKADDR_IN_BYTES_2: &[u8] = b"\x02\x00\xca\x6c\xc0\xa8\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00"; // 192.168.1.1:51820 const SOCKADDR_IN6_BYTES_1: &[u8] = b"\x0a\x00\xca\x6c\x10\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\xe4\x58\x8e\xad\x89\xbb\x8e\x25\x03\x00\x00\x00"; // fe80::e458:8ead:89bb:8e25%3:51820 (flow 16) #[test] fn test_parse_socket_addr_in_1() { let ipaddr = parse_socket_addr(SOCKADDR_IN_BYTES_1).unwrap(); assert_eq!(ipaddr, SocketAddrV4::new(Ipv4Addr::LOCALHOST, 7290).into()); } #[test] fn test_parse_socket_addr_in_2() { let ipaddr = parse_socket_addr(SOCKADDR_IN_BYTES_2).unwrap(); assert_eq!( ipaddr, SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 51820).into() ); } #[test] fn test_parse_socket_addr_in6_1() { let ipaddr = parse_socket_addr(SOCKADDR_IN6_BYTES_1).unwrap(); assert_eq!( ipaddr, SocketAddrV6::new( Ipv6Addr::from_str("fe80::e458:8ead:89bb:8e25").unwrap(), 51820, 16, 3 ) .into() ); } }