mptcp-pm-0.1.3/.cargo_vcs_info.json0000644000000001360000000000100125720ustar { "git": { "sha1": "a344a113752398cbba0ff5d7e26a22fd1d413112" }, "path_in_vcs": "" }mptcp-pm-0.1.3/.github/workflows/clippy-rustfmt.yml000064400000000000000000000012701046102023000205040ustar 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-tokio-socket run: cargo clippy - name: clippy-smol-socket run: cargo clippy --no-default-features --features smol_socket mptcp-pm-0.1.3/.github/workflows/license.yml000064400000000000000000000005201046102023000171210ustar 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 mptcp-pm-0.1.3/.github/workflows/main.yml000064400000000000000000000017101046102023000164250ustar 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 - name: Test with default feature env: # Needed root permission to modify MPTCP CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: "sudo -E" run: cargo test - name: Test with tokio feature env: # Needed root permission to modify MPTCP CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: "sudo -E" run: cargo test --features tokio_socket - name: Test with smol_socket feature env: # Needed root permission to modify MPTCP CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: "sudo -E" run: cargo test --features smol_socket mptcp-pm-0.1.3/.gitignore000064400000000000000000000000411046102023000133450ustar 00000000000000Cargo.lock target vendor/ *.swp mptcp-pm-0.1.3/.licenserc.yaml000064400000000000000000000003711046102023000142740ustar 00000000000000header: license: content: | SPDX-License-Identifier: MIT paths-ignore: - 'target' - '**/*.toml' - '**/*.lock' - '**/*.yml' - '**/*.md' - 'CHANGELOG' - 'LICENSE-MIT' - '.gitignore' comment: on-failure mptcp-pm-0.1.3/.rustfmt.toml000064400000000000000000000001141046102023000140350ustar 00000000000000max_width = 80 wrap_comments = true reorder_imports = true edition = "2021" mptcp-pm-0.1.3/CHANGELOG000064400000000000000000000004371046102023000126000ustar 00000000000000# Changelog ## [0.1.3] - 2023-07-10 ### Breaking changes - N/A ### New features - N/A ### Bug fixes - Use latest rust-netlink crates. (5ba35da) ## [0.1.2] - 2023-01-29 ### Breaking changes - N/A ### New features - N/A ### Bug fixes - Use latest rust-netlink crates. (b26fc3a) mptcp-pm-0.1.3/Cargo.lock0000644000000630750000000000100105600ustar # 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 = "async-channel" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", "futures-core", ] [[package]] name = "async-executor" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" dependencies = [ "async-lock", "async-task", "concurrent-queue", "fastrand", "futures-lite", "slab", ] [[package]] name = "async-global-executor" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", "async-io", "async-lock", "blocking", "futures-lite", "once_cell", ] [[package]] name = "async-io" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock", "autocfg", "cfg-if", "concurrent-queue", "futures-lite", "log", "parking", "polling", "rustix", "slab", "socket2", "waker-fn", ] [[package]] name = "async-lock" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" dependencies = [ "event-listener", ] [[package]] name = "async-std" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-channel", "async-global-executor", "async-io", "async-lock", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", "futures-lite", "gloo-timers", "kv-log-macro", "log", "memchr", "once_cell", "pin-project-lite", "pin-utils", "slab", "wasm-bindgen-futures", ] [[package]] name = "async-task" version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "atomic-waker" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", "winapi", ] [[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 = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blocking" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" dependencies = [ "async-channel", "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", "log", ] [[package]] name = "bumpalo" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[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 = "concurrent-queue" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "env_logger" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", "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 = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[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-lite" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ "fastrand", "futures-core", "futures-io", "memchr", "parking", "pin-project-lite", "waker-fn", ] [[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", ] [[package]] name = "gimli" version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "gloo-timers" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", ] [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[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 = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "io-lifetimes" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.2", "libc", "windows-sys", ] [[package]] name = "js-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "kv-log-macro" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ "log", ] [[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.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "log" version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" dependencies = [ "value-bag", ] [[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 = "mptcp-pm" version = "0.1.3" dependencies = [ "anyhow", "async-std", "byteorder", "env_logger", "futures", "genetlink", "log", "netlink-packet-core", "netlink-packet-generic", "netlink-packet-utils", "netlink-proto", "netlink-sys", "thiserror", "tokio", ] [[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-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 = [ "async-io", "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 0.3.2", "libc", ] [[package]] name = "object" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "parking" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" [[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 = "polling" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", "bitflags", "cfg-if", "concurrent-queue", "libc", "log", "pin-project-lite", "windows-sys", ] [[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.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags", "errno", "io-lifetimes", "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 = "value-bag" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", ] [[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" mptcp-pm-0.1.3/Cargo.toml0000644000000035540000000000100105770ustar # 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 = "mptcp-pm" version = "0.1.3" authors = ["Gris Ge "] description = "Linux kernel MPTCP path manager netlink Library" readme = "README.md" keywords = ["network"] categories = [ "network-programming", "os", ] license = "MIT" repository = "https://github.com/rust-netlink/mptcp-pm" [lib] name = "mptcp_pm" crate-type = ["lib"] path = "src/lib.rs" [dependencies.anyhow] version = "1.0.44" [dependencies.async-std] version = "1.9.0" optional = true [dependencies.byteorder] version = "1.4.3" [dependencies.futures] version = "0.3.17" [dependencies.genetlink] version = "0.2.5" default-features = false [dependencies.log] version = "0.4.14" [dependencies.netlink-packet-core] version = "0.7.0" [dependencies.netlink-packet-generic] version = "0.3.3" [dependencies.netlink-packet-utils] version = "0.5.2" [dependencies.netlink-proto] version = "0.11.2" default-features = false [dependencies.netlink-sys] version = "0.8.4" [dependencies.thiserror] version = "1.0.29" [dependencies.tokio] version = "1.0.1" features = ["rt"] optional = true [dev-dependencies.env_logger] version = "0.9.0" [dev-dependencies.tokio] version = "1.11.0" features = [ "macros", "rt", "rt-multi-thread", ] [features] default = ["tokio_socket"] smol_socket = [ "netlink-proto/smol_socket", "async-std", ] tokio_socket = [ "netlink-proto/tokio_socket", "tokio", ] mptcp-pm-0.1.3/Cargo.toml.orig000064400000000000000000000022411046102023000142500ustar 00000000000000[package] name = "mptcp-pm" version = "0.1.3" authors = ["Gris Ge "] license = "MIT" edition = "2018" description = "Linux kernel MPTCP path manager netlink Library" keywords = ["network"] categories = ["network-programming", "os"] readme = "README.md" repository = "https://github.com/rust-netlink/mptcp-pm" [lib] name = "mptcp_pm" path = "src/lib.rs" crate-type = ["lib"] [features] default = ["tokio_socket"] tokio_socket = ["netlink-proto/tokio_socket", "tokio"] smol_socket = ["netlink-proto/smol_socket", "async-std"] [dependencies] anyhow = "1.0.44" async-std = { version = "1.9.0", optional = true } byteorder = "1.4.3" futures = "0.3.17" log = "0.4.14" thiserror = "1.0.29" tokio = { version = "1.0.1", features = ["rt"], optional = true } genetlink = { default-features = false, version = "0.2.5" } netlink-packet-core = { version = "0.7.0" } netlink-packet-generic = { version = "0.3.3" } netlink-packet-utils = { version = "0.5.2" } netlink-proto = { default-features = false, version = "0.11.2" } netlink-sys = { version = "0.8.4" } [dev-dependencies] tokio = { version = "1.11.0", features = ["macros", "rt", "rt-multi-thread"] } env_logger = "0.9.0" mptcp-pm-0.1.3/LICENSE-MIT000064400000000000000000000027731046102023000130270ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Distributions of all or part of the Software intended to be used by the recipients as they would use the unmodified Software, containing modifications that substantially alter, remove, or disable functionality of the Software, outside of the documented configuration mechanisms provided by the Software, shall be modified such that the Original Author's bug reporting email addresses and urls are either replaced with the contact information of the parties responsible for the changes, or removed entirely. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mptcp-pm-0.1.3/README.md000064400000000000000000000000621046102023000126370ustar 00000000000000# Linux kernel MPTCP path manager netlink Library mptcp-pm-0.1.3/examples/dump_mptcp.rs000064400000000000000000000016531046102023000157230ustar 00000000000000// SPDX-License-Identifier: MIT use futures::stream::TryStreamExt; fn main() { let rt = tokio::runtime::Builder::new_current_thread() .enable_io() .build() .unwrap(); rt.block_on(get_addresses()); } async fn get_addresses() { let (connection, handle, _) = mptcp_pm::new_connection().unwrap(); tokio::spawn(connection); let mut address_handle = handle.address().get().execute().await; let mut msgs = Vec::new(); while let Some(msg) = address_handle.try_next().await.unwrap() { msgs.push(msg); } assert!(!msgs.is_empty()); for msg in msgs { println!("{msg:?}"); } let mut limits_handle = handle.limits().get().execute().await; let mut msgs = Vec::new(); while let Some(msg) = limits_handle.try_next().await.unwrap() { msgs.push(msg); } assert!(!msgs.is_empty()); for msg in msgs { println!("{msg:?}"); } } mptcp-pm-0.1.3/src/address/attr.rs000064400000000000000000000141621046102023000151220ustar 00000000000000// SPDX-License-Identifier: MIT use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use anyhow::Context; use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{DefaultNla, Nla, NlaBuffer}, parsers::{parse_i32, parse_ip, parse_u16, parse_u32, parse_u8}, DecodeError, Emitable, Parseable, }; const MPTCP_PM_ADDR_ATTR_FAMILY: u16 = 1; const MPTCP_PM_ADDR_ATTR_ID: u16 = 2; const MPTCP_PM_ADDR_ATTR_ADDR4: u16 = 3; const MPTCP_PM_ADDR_ATTR_ADDR6: u16 = 4; const MPTCP_PM_ADDR_ATTR_PORT: u16 = 5; const MPTCP_PM_ADDR_ATTR_FLAGS: u16 = 6; const MPTCP_PM_ADDR_ATTR_IF_IDX: u16 = 7; const MPTCP_PM_ADDR_FLAG_SIGNAL: u32 = 1 << 0; const MPTCP_PM_ADDR_FLAG_SUBFLOW: u32 = 1 << 1; const MPTCP_PM_ADDR_FLAG_BACKUP: u32 = 1 << 2; const MPTCP_PM_ADDR_FLAG_FULLMESH: u32 = 1 << 3; const MPTCP_PM_ADDR_FLAG_IMPLICIT: u32 = 1 << 4; #[derive(Debug, PartialEq, Eq, Clone)] pub enum MptcpPathManagerAddressAttrFlag { Signal, Subflow, Backup, Fullmesh, Implicit, Other(u32), } fn u32_to_vec_flags(value: u32) -> Vec { let mut ret = Vec::new(); let mut found = 0u32; if (value & MPTCP_PM_ADDR_FLAG_SIGNAL) > 0 { found += MPTCP_PM_ADDR_FLAG_SIGNAL; ret.push(MptcpPathManagerAddressAttrFlag::Signal); } if (value & MPTCP_PM_ADDR_FLAG_SUBFLOW) > 0 { found += MPTCP_PM_ADDR_FLAG_SUBFLOW; ret.push(MptcpPathManagerAddressAttrFlag::Subflow); } if (value & MPTCP_PM_ADDR_FLAG_BACKUP) > 0 { found += MPTCP_PM_ADDR_FLAG_BACKUP; ret.push(MptcpPathManagerAddressAttrFlag::Backup); } if (value & MPTCP_PM_ADDR_FLAG_FULLMESH) > 0 { found += MPTCP_PM_ADDR_FLAG_FULLMESH; ret.push(MptcpPathManagerAddressAttrFlag::Fullmesh); } if (value & MPTCP_PM_ADDR_FLAG_IMPLICIT) > 0 { found += MPTCP_PM_ADDR_FLAG_IMPLICIT; ret.push(MptcpPathManagerAddressAttrFlag::Implicit); } if (value - found) > 0 { ret.push(MptcpPathManagerAddressAttrFlag::Other(value - found)); } ret } impl From<&MptcpPathManagerAddressAttrFlag> for u32 { fn from(v: &MptcpPathManagerAddressAttrFlag) -> u32 { match v { MptcpPathManagerAddressAttrFlag::Signal => { MPTCP_PM_ADDR_FLAG_SIGNAL } MptcpPathManagerAddressAttrFlag::Subflow => { MPTCP_PM_ADDR_FLAG_SUBFLOW } MptcpPathManagerAddressAttrFlag::Backup => { MPTCP_PM_ADDR_FLAG_BACKUP } MptcpPathManagerAddressAttrFlag::Fullmesh => { MPTCP_PM_ADDR_FLAG_FULLMESH } MptcpPathManagerAddressAttrFlag::Implicit => { MPTCP_PM_ADDR_FLAG_IMPLICIT } MptcpPathManagerAddressAttrFlag::Other(d) => *d, } } } #[derive(Debug, PartialEq, Eq, Clone)] pub enum MptcpPathManagerAddressAttr { Family(u16), Id(u8), Addr4(Ipv4Addr), Addr6(Ipv6Addr), Port(u16), Flags(Vec), IfIndex(i32), Other(DefaultNla), } impl Nla for MptcpPathManagerAddressAttr { fn value_len(&self) -> usize { match self { Self::Family(_) | Self::Port(_) => 2, Self::Addr4(_) | Self::Flags(_) | Self::IfIndex(_) => 4, Self::Id(_) => 1, Self::Addr6(_) => 16, Self::Other(attr) => attr.value_len(), } } fn kind(&self) -> u16 { match self { Self::Family(_) => MPTCP_PM_ADDR_ATTR_FAMILY, Self::Id(_) => MPTCP_PM_ADDR_ATTR_ID, Self::Addr4(_) => MPTCP_PM_ADDR_ATTR_ADDR4, Self::Addr6(_) => MPTCP_PM_ADDR_ATTR_ADDR6, Self::Port(_) => MPTCP_PM_ADDR_ATTR_PORT, Self::Flags(_) => MPTCP_PM_ADDR_ATTR_FLAGS, Self::IfIndex(_) => MPTCP_PM_ADDR_ATTR_IF_IDX, Self::Other(attr) => attr.kind(), } } fn emit_value(&self, buffer: &mut [u8]) { match self { Self::Family(d) | Self::Port(d) => { NativeEndian::write_u16(buffer, *d) } Self::Addr4(i) => buffer.copy_from_slice(&i.octets()), Self::Addr6(i) => buffer.copy_from_slice(&i.octets()), Self::Id(d) => buffer[0] = *d, Self::Flags(flags) => { let mut value = 0u32; for flag in flags { value += u32::from(flag); } NativeEndian::write_u32(buffer, value) } Self::IfIndex(d) => NativeEndian::write_i32(buffer, *d), Self::Other(ref attr) => attr.emit(buffer), } } } impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for MptcpPathManagerAddressAttr { fn parse(buf: &NlaBuffer<&'a T>) -> Result { let payload = buf.value(); Ok(match buf.kind() { MPTCP_PM_ADDR_ATTR_FAMILY => { let err_msg = format!("Invalid MPTCP_PM_ADDR_ATTR_FAMILY value {payload:?}"); Self::Family(parse_u16(payload).context(err_msg)?) } MPTCP_PM_ADDR_ATTR_ID => { Self::Id(parse_u8(payload).context("Invalid MPTCP_PM_ADDR_ATTR_ID value")?) } MPTCP_PM_ADDR_ATTR_ADDR4 | MPTCP_PM_ADDR_ATTR_ADDR6 => { match parse_ip(payload) .context("Invalid MPTCP_PM_ADDR_ATTR_ADDR4/MPTCP_PM_ADDR_ATTR_ADDR6 value")? { IpAddr::V4(i) => Self::Addr4(i), IpAddr::V6(i) => Self::Addr6(i), } } MPTCP_PM_ADDR_ATTR_PORT => { Self::Port(parse_u16(payload).context("Invalid MPTCP_PM_ADDR_ATTR_PORT value")?) } MPTCP_PM_ADDR_ATTR_FLAGS => Self::Flags(u32_to_vec_flags( parse_u32(payload).context("Invalid MPTCP_PM_ADDR_ATTR_FLAGS value")?, )), MPTCP_PM_ADDR_ATTR_IF_IDX => Self::IfIndex( parse_i32(payload).context("Invalid MPTCP_PM_ADDR_ATTR_IF_IDX value")?, ), _ => Self::Other(DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?), }) } } mptcp-pm-0.1.3/src/address/get.rs000064400000000000000000000014671046102023000147330ustar 00000000000000// SPDX-License-Identifier: MIT use futures::TryStream; use netlink_packet_generic::GenlMessage; use crate::{ mptcp_execute, MptcpPathManagerError, MptcpPathManagerHandle, MptcpPathManagerMessage, }; pub struct MptcpPathManagerAddressGetRequest { handle: MptcpPathManagerHandle, } impl MptcpPathManagerAddressGetRequest { pub(crate) fn new(handle: MptcpPathManagerHandle) -> Self { MptcpPathManagerAddressGetRequest { handle } } pub async fn execute( self, ) -> impl TryStream< Ok = GenlMessage, Error = MptcpPathManagerError, > { let MptcpPathManagerAddressGetRequest { mut handle } = self; let mptcp_msg = MptcpPathManagerMessage::new_address_get(); mptcp_execute(&mut handle, mptcp_msg).await } } mptcp-pm-0.1.3/src/address/handle.rs000064400000000000000000000010471046102023000154010ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{MptcpPathManagerAddressGetRequest, MptcpPathManagerHandle}; pub struct MptcpPathManagerAddressHandle(MptcpPathManagerHandle); impl MptcpPathManagerAddressHandle { pub fn new(handle: MptcpPathManagerHandle) -> Self { MptcpPathManagerAddressHandle(handle) } /// Retrieve the multipath-TCP addresses /// (equivalent to `ip mptcp endpoint show`) pub fn get(&mut self) -> MptcpPathManagerAddressGetRequest { MptcpPathManagerAddressGetRequest::new(self.0.clone()) } } mptcp-pm-0.1.3/src/address/mod.rs000064400000000000000000000003561046102023000147270ustar 00000000000000// SPDX-License-Identifier: MIT mod attr; mod get; mod handle; pub use attr::{MptcpPathManagerAddressAttr, MptcpPathManagerAddressAttrFlag}; pub use get::MptcpPathManagerAddressGetRequest; pub use handle::MptcpPathManagerAddressHandle; mptcp-pm-0.1.3/src/connection.rs000064400000000000000000000016751046102023000146670ustar 00000000000000// SPDX-License-Identifier: MIT use std::io; use futures::channel::mpsc::UnboundedReceiver; use genetlink::message::RawGenlMessage; use netlink_packet_core::NetlinkMessage; use netlink_proto::Connection; use netlink_sys::{AsyncSocket, SocketAddr}; use crate::MptcpPathManagerHandle; #[cfg(feature = "tokio_socket")] #[allow(clippy::type_complexity)] pub fn new_connection() -> io::Result<( Connection, MptcpPathManagerHandle, UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> { new_connection_with_socket() } #[allow(clippy::type_complexity)] pub fn new_connection_with_socket() -> io::Result<( Connection, MptcpPathManagerHandle, UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> where S: AsyncSocket, { let (conn, handle, messages) = genetlink::new_connection_with_socket()?; Ok((conn, MptcpPathManagerHandle::new(handle), messages)) } mptcp-pm-0.1.3/src/error.rs000064400000000000000000000011441046102023000136500ustar 00000000000000// SPDX-License-Identifier: MIT use thiserror::Error; use netlink_packet_core::{ErrorMessage, NetlinkMessage}; use netlink_packet_generic::GenlMessage; use crate::MptcpPathManagerMessage; #[derive(Clone, Eq, PartialEq, Debug, Error)] pub enum MptcpPathManagerError { #[error("Received an unexpected message {0:?}")] UnexpectedMessage(NetlinkMessage>), #[error("Received a netlink error message {0}")] NetlinkError(ErrorMessage), #[error("A netlink request failed")] RequestFailed(String), #[error("A bug in this crate")] Bug(String), } mptcp-pm-0.1.3/src/handle.rs000064400000000000000000000050261046102023000137550ustar 00000000000000// SPDX-License-Identifier: MIT use futures::{future::Either, FutureExt, Stream, StreamExt, TryStream}; use genetlink::GenetlinkHandle; use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST}; use netlink_packet_generic::GenlMessage; use netlink_packet_utils::DecodeError; use crate::{ try_mptcp, MptcpPathManagerAddressHandle, MptcpPathManagerCmd, MptcpPathManagerError, MptcpPathManagerLimitsHandle, MptcpPathManagerMessage, }; #[derive(Clone, Debug)] pub struct MptcpPathManagerHandle { pub handle: GenetlinkHandle, } impl MptcpPathManagerHandle { pub(crate) fn new(handle: GenetlinkHandle) -> Self { MptcpPathManagerHandle { handle } } // equivalent to `ip mptcp endpoint` command // Instead of using `endpoint`, we are aligning with kernel netlink name // `address` here. pub fn address(&self) -> MptcpPathManagerAddressHandle { MptcpPathManagerAddressHandle::new(self.clone()) } // equivalent to `ip mptcp limits` command pub fn limits(&self) -> MptcpPathManagerLimitsHandle { MptcpPathManagerLimitsHandle::new(self.clone()) } pub async fn request( &mut self, message: NetlinkMessage>, ) -> Result< impl Stream< Item = Result< NetlinkMessage>, DecodeError, >, >, MptcpPathManagerError, > { self.handle.request(message).await.map_err(|e| { MptcpPathManagerError::RequestFailed(format!( "BUG: Request failed with {e}" )) }) } } pub(crate) async fn mptcp_execute( handle: &mut MptcpPathManagerHandle, mptcp_msg: MptcpPathManagerMessage, ) -> impl TryStream< Ok = GenlMessage, Error = MptcpPathManagerError, > { let nl_header_flags = match mptcp_msg.cmd { MptcpPathManagerCmd::AddressGet => NLM_F_REQUEST | NLM_F_DUMP, MptcpPathManagerCmd::LimitsGet => NLM_F_REQUEST, }; let mut nl_msg = NetlinkMessage::from(GenlMessage::from_payload(mptcp_msg)); nl_msg.header.flags = nl_header_flags; match handle.request(nl_msg).await { Ok(response) => { Either::Left(response.map(move |msg| Ok(try_mptcp!(msg)))) } Err(e) => Either::Right( futures::future::err::< GenlMessage, MptcpPathManagerError, >(e) .into_stream(), ), } } mptcp-pm-0.1.3/src/lib.rs000064400000000000000000000013321046102023000132640ustar 00000000000000// SPDX-License-Identifier: MIT mod address; mod connection; mod error; mod handle; mod limits; mod macros; mod message; pub use address::{ MptcpPathManagerAddressAttr, MptcpPathManagerAddressAttrFlag, MptcpPathManagerAddressGetRequest, MptcpPathManagerAddressHandle, }; #[cfg(feature = "tokio_socket")] pub use connection::new_connection; pub use connection::new_connection_with_socket; pub use error::MptcpPathManagerError; pub use handle::MptcpPathManagerHandle; pub use limits::{ MptcpPathManagerLimitsAttr, MptcpPathManagerLimitsGetRequest, MptcpPathManagerLimitsHandle, }; pub use message::{ MptcpPathManagerAttr, MptcpPathManagerCmd, MptcpPathManagerMessage, }; pub(crate) use handle::mptcp_execute; mptcp-pm-0.1.3/src/limits/attr.rs000064400000000000000000000035311046102023000147740ustar 00000000000000// SPDX-License-Identifier: MIT use anyhow::Context; use byteorder::{ByteOrder, NativeEndian}; use netlink_packet_utils::{ nla::{DefaultNla, Nla, NlaBuffer}, parsers::parse_u32, DecodeError, Emitable, Parseable, }; const MPTCP_PM_ATTR_RCV_ADD_ADDRS: u16 = 2; const MPTCP_PM_ATTR_SUBFLOWS: u16 = 3; #[derive(Debug, PartialEq, Eq, Clone)] pub enum MptcpPathManagerLimitsAttr { RcvAddAddrs(u32), Subflows(u32), Other(DefaultNla), } impl Nla for MptcpPathManagerLimitsAttr { fn value_len(&self) -> usize { match self { Self::Other(attr) => attr.value_len(), _ => 4, } } fn kind(&self) -> u16 { match self { Self::RcvAddAddrs(_) => MPTCP_PM_ATTR_RCV_ADD_ADDRS, Self::Subflows(_) => MPTCP_PM_ATTR_SUBFLOWS, Self::Other(attr) => attr.kind(), } } fn emit_value(&self, buffer: &mut [u8]) { match self { Self::RcvAddAddrs(d) | Self::Subflows(d) => { NativeEndian::write_u32(buffer, *d) } Self::Other(ref attr) => attr.emit(buffer), } } } impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> for MptcpPathManagerLimitsAttr { fn parse(buf: &NlaBuffer<&'a T>) -> Result { let payload = buf.value(); Ok(match buf.kind() { MPTCP_PM_ATTR_RCV_ADD_ADDRS => Self::RcvAddAddrs( parse_u32(payload) .context("Invalid MPTCP_PM_ATTR_RCV_ADD_ADDRS value")?, ), MPTCP_PM_ATTR_SUBFLOWS => Self::Subflows( parse_u32(payload) .context("Invalid MPTCP_PM_ATTR_SUBFLOWS value")?, ), _ => Self::Other( DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?, ), }) } } mptcp-pm-0.1.3/src/limits/get.rs000064400000000000000000000014621046102023000146020ustar 00000000000000// SPDX-License-Identifier: MIT use futures::TryStream; use netlink_packet_generic::GenlMessage; use crate::{ mptcp_execute, MptcpPathManagerError, MptcpPathManagerHandle, MptcpPathManagerMessage, }; pub struct MptcpPathManagerLimitsGetRequest { handle: MptcpPathManagerHandle, } impl MptcpPathManagerLimitsGetRequest { pub(crate) fn new(handle: MptcpPathManagerHandle) -> Self { MptcpPathManagerLimitsGetRequest { handle } } pub async fn execute( self, ) -> impl TryStream< Ok = GenlMessage, Error = MptcpPathManagerError, > { let MptcpPathManagerLimitsGetRequest { mut handle } = self; let mptcp_msg = MptcpPathManagerMessage::new_limits_get(); mptcp_execute(&mut handle, mptcp_msg).await } } mptcp-pm-0.1.3/src/limits/handle.rs000064400000000000000000000010411046102023000152470ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{MptcpPathManagerHandle, MptcpPathManagerLimitsGetRequest}; pub struct MptcpPathManagerLimitsHandle(MptcpPathManagerHandle); impl MptcpPathManagerLimitsHandle { pub fn new(handle: MptcpPathManagerHandle) -> Self { MptcpPathManagerLimitsHandle(handle) } /// Retrieve the multipath-TCP addresses /// (equivalent to `ip mptcp endpoint show`) pub fn get(&mut self) -> MptcpPathManagerLimitsGetRequest { MptcpPathManagerLimitsGetRequest::new(self.0.clone()) } } mptcp-pm-0.1.3/src/limits/mod.rs000064400000000000000000000003101046102023000145710ustar 00000000000000// SPDX-License-Identifier: MIT mod attr; mod get; mod handle; pub use attr::MptcpPathManagerLimitsAttr; pub use get::MptcpPathManagerLimitsGetRequest; pub use handle::MptcpPathManagerLimitsHandle; mptcp-pm-0.1.3/src/macros.rs000064400000000000000000000017711046102023000140110ustar 00000000000000// SPDX-License-Identifier: MIT #[macro_export] macro_rules! try_mptcp { ($msg: expr) => {{ use netlink_packet_core::{NetlinkMessage, NetlinkPayload}; use $crate::MptcpPathManagerError; match $msg { Ok(msg) => { let (header, payload) = msg.into_parts(); match payload { NetlinkPayload::InnerMessage(msg) => msg, NetlinkPayload::Error(err) => { return Err(MptcpPathManagerError::NetlinkError(err)) } _ => { return Err(MptcpPathManagerError::UnexpectedMessage( NetlinkMessage::new(header, payload), )) } } } Err(e) => { return Err(MptcpPathManagerError::Bug(format!( "BUG: decode error {:?}", e ))) } } }}; } mptcp-pm-0.1.3/src/message.rs000064400000000000000000000117671046102023000141570ustar 00000000000000// SPDX-License-Identifier: MIT use anyhow::Context; use netlink_packet_generic::{GenlFamily, GenlHeader}; use netlink_packet_utils::{ nla::{DefaultNla, Nla, NlasIterator}, DecodeError, Emitable, Parseable, ParseableParametrized, }; use crate::{ address::MptcpPathManagerAddressAttr, limits::MptcpPathManagerLimitsAttr, }; const MPTCP_PM_CMD_GET_ADDR: u8 = 3; const MPTCP_PM_CMD_GET_LIMITS: u8 = 6; const MPTCP_PM_ATTR_ADDR: u16 = 1; const MPTCP_PM_ATTR_RCV_ADD_ADDRS: u16 = 2; const MPTCP_PM_ATTR_SUBFLOWS: u16 = 3; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum MptcpPathManagerCmd { AddressGet, LimitsGet, } impl From for u8 { fn from(cmd: MptcpPathManagerCmd) -> Self { match cmd { MptcpPathManagerCmd::AddressGet => MPTCP_PM_CMD_GET_ADDR, MptcpPathManagerCmd::LimitsGet => MPTCP_PM_CMD_GET_LIMITS, } } } #[derive(Debug, PartialEq, Eq, Clone)] pub enum MptcpPathManagerAttr { Address(MptcpPathManagerAddressAttr), Limits(MptcpPathManagerLimitsAttr), Other(DefaultNla), } impl Nla for MptcpPathManagerAttr { fn value_len(&self) -> usize { match self { Self::Address(attr) => attr.value_len(), Self::Limits(attr) => attr.value_len(), Self::Other(attr) => attr.value_len(), } } fn kind(&self) -> u16 { match self { Self::Address(attr) => attr.kind(), Self::Limits(attr) => attr.kind(), Self::Other(attr) => attr.kind(), } } fn emit_value(&self, buffer: &mut [u8]) { match self { Self::Address(attr) => attr.emit_value(buffer), Self::Limits(attr) => attr.emit_value(buffer), Self::Other(ref attr) => attr.emit(buffer), } } } #[derive(Debug, PartialEq, Eq, Clone)] pub struct MptcpPathManagerMessage { pub cmd: MptcpPathManagerCmd, pub nlas: Vec, } impl GenlFamily for MptcpPathManagerMessage { fn family_name() -> &'static str { "mptcp_pm" } fn version(&self) -> u8 { 1 } fn command(&self) -> u8 { self.cmd.into() } } impl MptcpPathManagerMessage { pub fn new_address_get() -> Self { MptcpPathManagerMessage { cmd: MptcpPathManagerCmd::AddressGet, nlas: vec![], } } pub fn new_limits_get() -> Self { MptcpPathManagerMessage { cmd: MptcpPathManagerCmd::LimitsGet, nlas: vec![], } } } impl Emitable for MptcpPathManagerMessage { fn buffer_len(&self) -> usize { self.nlas.as_slice().buffer_len() } fn emit(&self, buffer: &mut [u8]) { self.nlas.as_slice().emit(buffer) } } fn parse_nlas(buffer: &[u8]) -> Result, DecodeError> { let mut nlas = Vec::new(); for nla in NlasIterator::new(buffer) { let error_msg = format!("Failed to parse mptcp address message attribute {nla:?}"); let nla = &nla.context(error_msg)?; match nla.kind() { MPTCP_PM_ATTR_ADDR => { for addr_nla in NlasIterator::new(nla.value()) { let error_msg = format!( "Failed to parse MPTCP_PM_ATTR_ADDR {addr_nla:?}" ); let addr_nla = &addr_nla.context(error_msg)?; nlas.push(MptcpPathManagerAttr::Address( MptcpPathManagerAddressAttr::parse(addr_nla) .context("Failed to parse MPTCP_PM_ATTR_ADDR")?, )) } } MPTCP_PM_ATTR_RCV_ADD_ADDRS => { nlas.push(MptcpPathManagerAttr::Limits( MptcpPathManagerLimitsAttr::parse(nla).context( "Failed to parse MPTCP_PM_ATTR_RCV_ADD_ADDRS", )?, )) } MPTCP_PM_ATTR_SUBFLOWS => nlas.push(MptcpPathManagerAttr::Limits( MptcpPathManagerLimitsAttr::parse(nla) .context("Failed to parse MPTCP_PM_ATTR_RCV_ADD_ADDRS")?, )), _ => nlas.push(MptcpPathManagerAttr::Other( DefaultNla::parse(nla).context("invalid NLA (unknown kind)")?, )), } } Ok(nlas) } impl ParseableParametrized<[u8], GenlHeader> for MptcpPathManagerMessage { fn parse_with_param( buffer: &[u8], header: GenlHeader, ) -> Result { Ok(match header.cmd { MPTCP_PM_CMD_GET_ADDR => Self { cmd: MptcpPathManagerCmd::AddressGet, nlas: parse_nlas(buffer)?, }, MPTCP_PM_CMD_GET_LIMITS => Self { cmd: MptcpPathManagerCmd::LimitsGet, nlas: parse_nlas(buffer)?, }, cmd => { return Err(DecodeError::from(format!( "Unsupported mptcp reply command: {cmd}" ))) } }) } } mptcp-pm-0.1.3/tests/dump_mptcp.rs000064400000000000000000000035131046102023000152440ustar 00000000000000// SPDX-License-Identifier: MIT use futures::stream::TryStreamExt; use std::process::Command; use mptcp_pm::{MptcpPathManagerAttr, MptcpPathManagerLimitsAttr}; #[test] fn test_mptcp_empty_addresses_and_limits() { Command::new("sysctl") .arg("-w") .arg("net.mptcp.enabled=1") .spawn() .unwrap(); // OK to fail as Github CI has no ip-mptcp Command::new("ip") .arg("mptcp") .arg("endpoint") .arg("flush") .spawn() .ok(); // OK to fail as Github CI has no ip-mptcp Command::new("ip") .arg("mptcp") .arg("limits") .arg("set") .arg("subflows") .arg("0") .arg("add_addr_accepted") .arg("0") .spawn() .ok(); let rt = tokio::runtime::Builder::new_current_thread() .enable_io() .build() .unwrap(); rt.block_on(assert_empty_addresses_and_limits()); } async fn assert_empty_addresses_and_limits() { let (connection, handle, _) = mptcp_pm::new_connection().unwrap(); tokio::spawn(connection); let mut address_handle = handle.address().get().execute().await; let mut msgs = Vec::new(); while let Some(msg) = address_handle.try_next().await.unwrap() { msgs.push(msg); } assert!(msgs.is_empty()); let mut limits_handle = handle.limits().get().execute().await; let mut msgs = Vec::new(); while let Some(msg) = limits_handle.try_next().await.unwrap() { msgs.push(msg); } assert_eq!(msgs.len(), 1); let mptcp_nlas = &msgs[0].payload.nlas; assert_eq!( mptcp_nlas[0], MptcpPathManagerAttr::Limits(MptcpPathManagerLimitsAttr::RcvAddAddrs( 0 )) ); assert_eq!( mptcp_nlas[1], MptcpPathManagerAttr::Limits(MptcpPathManagerLimitsAttr::Subflows(0)) ); }