genetlink-0.2.5/.cargo_vcs_info.json0000644000000001360000000000100130200ustar { "git": { "sha1": "b8c3e74b7a967c87e1fd2a2406ac1a221665e15d" }, "path_in_vcs": "" }genetlink-0.2.5/.github/workflows/clippy-rustfmt.yml000064400000000000000000000012531046102023000207330ustar 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 - name: clippy-smol-socket run: cargo clippy --no-default-features --features smol_socket genetlink-0.2.5/.github/workflows/license.yml000064400000000000000000000005201046102023000173470ustar 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 genetlink-0.2.5/.github/workflows/main.yml000064400000000000000000000011021046102023000166460ustar 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 run: cargo test - name: Test with tokio feature run: cargo test --features tokio_socket - name: Test with smol_socket feature run: cargo test --features smol_socket genetlink-0.2.5/.gitignore000064400000000000000000000000411046102023000135730ustar 00000000000000Cargo.lock target vendor/ *.swp genetlink-0.2.5/.licenserc.yaml000064400000000000000000000003711046102023000145220ustar 00000000000000header: license: content: | SPDX-License-Identifier: MIT paths-ignore: - 'target' - '**/*.toml' - '**/*.lock' - '**/*.yml' - '**/*.md' - 'CHANGELOG' - 'LICENSE-MIT' - '.gitignore' comment: on-failure genetlink-0.2.5/.rustfmt.toml000064400000000000000000000001141046102023000142630ustar 00000000000000max_width = 80 wrap_comments = true reorder_imports = true edition = "2021" genetlink-0.2.5/CHANGELOG000064400000000000000000000004371046102023000130260ustar 00000000000000# Changelog ## [0.2.5] - 2023-07-10 ### Breaking changes - N/A ### New features - N/A ### Bug fixes - Use latest rust-netlink crates. (43f99db) ## [0.2.4] - 2023-01-29 ### Breaking changes - N/A ### New features - N/A ### Bug fixes - Use latest rust-netlink crates. (77c37a8) genetlink-0.2.5/Cargo.lock0000644000000555740000000000100110130ustar # 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 = "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 = "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 = "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" dependencies = [ "anyhow", "async-std", "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 = "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.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[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", "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 = "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", "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 = "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 = "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-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" genetlink-0.2.5/Cargo.toml0000644000000034020000000000100110150ustar # 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 = "genetlink" version = "0.2.5" authors = ["Leo "] description = "communicate with generic netlink" homepage = "https://github.com/rust-netlink/genetlink" readme = "README.md" keywords = [ "netlink", "linux", ] license = "MIT" repository = "https://github.com/rust-netlink/genetlink" [[example]] name = "list_genetlink_family" required-features = ["tokio_socket"] [[example]] name = "dump_family_policy" required-features = ["tokio_socket"] [dependencies.async-std] version = "1.9.0" optional = true [dependencies.futures] version = "0.3.16" [dependencies.log] version = "0.4" [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.thiserror] version = "1.0.26" [dependencies.tokio] version = "1.9.0" features = ["rt"] optional = true [dev-dependencies.anyhow] version = "1.0.42" [dev-dependencies.tokio] version = "1.9.0" features = [ "rt", "rt-multi-thread", "macros", ] [features] default = ["tokio_socket"] smol_socket = [ "netlink-proto/smol_socket", "async-std", ] tokio_socket = [ "netlink-proto/tokio_socket", "tokio", ] genetlink-0.2.5/Cargo.toml.orig000064400000000000000000000021711046102023000145000ustar 00000000000000[package] name = "genetlink" version = "0.2.5" authors = ["Leo "] edition = "2018" homepage = "https://github.com/rust-netlink/genetlink" repository = "https://github.com/rust-netlink/genetlink" keywords = ["netlink", "linux"] license = "MIT" readme = "README.md" description = "communicate with generic netlink" [features] default = ["tokio_socket"] tokio_socket = ["netlink-proto/tokio_socket", "tokio"] smol_socket = ["netlink-proto/smol_socket","async-std"] [dependencies] futures = "0.3.16" netlink-proto = { default-features = false, version = "0.11.2" } netlink-packet-generic = { version = "0.3.3" } netlink-packet-utils = { version = "0.5.2" } netlink-packet-core = { version = "0.7.0" } tokio = { version = "1.9.0", features = ["rt"], optional = true } async-std = { version = "1.9.0", optional = true } thiserror = "1.0.26" log = "0.4" [dev-dependencies] anyhow = "1.0.42" tokio = { version = "1.9.0", features = ["rt", "rt-multi-thread", "macros"] } [[example]] name = "list_genetlink_family" required-features = ["tokio_socket"] [[example]] name = "dump_family_policy" required-features = ["tokio_socket"] genetlink-0.2.5/LICENSE-MIT000064400000000000000000000027731046102023000132550ustar 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. genetlink-0.2.5/README.md000064400000000000000000000004201046102023000130630ustar 00000000000000# Rust crate for generic netlink protocol This crate provides higher level abstraction for the [generic netlink protocol][1]. Rust crate document could be found at [docs.rs][2]. [1]: https://www.man7.org/linux/man-pages/man8/genl.8.html [2]: https://docs.rs/genetlink genetlink-0.2.5/examples/dump_family_policy.rs000064400000000000000000000030531046102023000176620ustar 00000000000000// SPDX-License-Identifier: MIT use std::env::args; use anyhow::{bail, Error}; use futures::StreamExt; use genetlink::new_connection; use netlink_packet_core::{ NetlinkHeader, NetlinkMessage, NetlinkPayload, NLM_F_DUMP, NLM_F_REQUEST, }; use netlink_packet_generic::{ ctrl::{nlas::GenlCtrlAttrs, GenlCtrl, GenlCtrlCmd}, GenlMessage, }; #[tokio::main] async fn main() -> Result<(), Error> { let argv: Vec<_> = args().collect(); if argv.len() < 2 { eprintln!("Usage: dump_family_policy "); bail!("Required arguments not given"); } let mut nl_hdr = NetlinkHeader::default(); nl_hdr.flags = NLM_F_REQUEST | NLM_F_DUMP; let nlmsg = NetlinkMessage::new( nl_hdr, GenlMessage::from_payload(GenlCtrl { cmd: GenlCtrlCmd::GetPolicy, nlas: vec![GenlCtrlAttrs::FamilyName(argv[1].to_owned())], }) .into(), ); let (conn, mut handle, _) = new_connection()?; tokio::spawn(conn); let mut responses = handle.request(nlmsg).await?; while let Some(result) = responses.next().await { let resp = result?; match resp.payload { NetlinkPayload::InnerMessage(genlmsg) => { if genlmsg.payload.cmd == GenlCtrlCmd::GetPolicy { println!("<<< {genlmsg:?}"); } } NetlinkPayload::Error(err) => { eprintln!("Received a netlink error message: {err:?}"); bail!(err); } _ => {} } } Ok(()) } genetlink-0.2.5/examples/list_genetlink_family.rs000064400000000000000000000056601046102023000203570ustar 00000000000000// SPDX-License-Identifier: MIT //! Example of listing generic families based on `netlink_proto` //! //! This example's functionality is same as the identical name example in //! `netlink_packet_generic`. But this example shows you the usage of this crate //! to run generic netlink protocol asynchronously. use anyhow::{bail, Error}; use futures::StreamExt; use genetlink::new_connection; use netlink_packet_core::{ NetlinkHeader, NetlinkMessage, NetlinkPayload, NLM_F_DUMP, NLM_F_REQUEST, }; use netlink_packet_generic::{ ctrl::{nlas::GenlCtrlAttrs, GenlCtrl, GenlCtrlCmd}, GenlMessage, }; #[tokio::main] async fn main() -> Result<(), Error> { let mut nl_hdr = NetlinkHeader::default(); nl_hdr.flags = NLM_F_REQUEST | NLM_F_DUMP; let nlmsg = NetlinkMessage::new( nl_hdr, GenlMessage::from_payload(GenlCtrl { cmd: GenlCtrlCmd::GetFamily, nlas: vec![], }) .into(), ); let (conn, mut handle, _) = new_connection()?; tokio::spawn(conn); let mut responses = handle.request(nlmsg).await?; while let Some(result) = responses.next().await { let resp = result?; match resp.payload { NetlinkPayload::InnerMessage(genlmsg) => { if genlmsg.payload.cmd == GenlCtrlCmd::NewFamily { print_entry(genlmsg.payload.nlas); } } NetlinkPayload::Error(err) => { eprintln!("Received a netlink error message: {err:?}"); bail!(err); } _ => {} } } Ok(()) } fn print_entry(entry: Vec) { let family_id = entry .iter() .find_map(|nla| { if let GenlCtrlAttrs::FamilyId(id) = nla { Some(*id) } else { None } }) .expect("Cannot find FamilyId attribute"); let family_name = entry .iter() .find_map(|nla| { if let GenlCtrlAttrs::FamilyName(name) = nla { Some(name.as_str()) } else { None } }) .expect("Cannot find FamilyName attribute"); let version = entry .iter() .find_map(|nla| { if let GenlCtrlAttrs::Version(ver) = nla { Some(*ver) } else { None } }) .expect("Cannot find Version attribute"); let hdrsize = entry .iter() .find_map(|nla| { if let GenlCtrlAttrs::HdrSize(hdr) = nla { Some(*hdr) } else { None } }) .expect("Cannot find HdrSize attribute"); if hdrsize == 0 { println!("0x{family_id:04x} {family_name} [Version {version}]"); } else { println!( "0x{family_id:04x} {family_name} [Version {version}] \ [Header {hdrsize} bytes]" ); } } genetlink-0.2.5/src/connection.rs000064400000000000000000000033411046102023000151050ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{message::RawGenlMessage, GenetlinkHandle}; use futures::channel::mpsc::UnboundedReceiver; use netlink_packet_core::NetlinkMessage; use netlink_proto::{ self, sys::{protocols::NETLINK_GENERIC, AsyncSocket, SocketAddr}, Connection, }; use std::io; /// Construct a generic netlink connection /// /// The function would return a tuple containing three objects. /// - an async netlink connection /// - a connection handle to interact with the connection /// - a receiver of the unsolicited messages /// /// The connection object is also a event loop which implements /// [`std::future::Future`]. In most cases, users spawn it on an async runtime /// and use the handle to send messages. For detailed documentation, please /// refer to [`netlink_proto::new_connection`]. /// /// The [`GenetlinkHandle`] can send and receive any type of generic netlink /// message. And it can automatic resolve the generic family id before sending. #[cfg(feature = "tokio_socket")] #[allow(clippy::type_complexity)] pub fn new_connection() -> io::Result<( Connection, GenetlinkHandle, UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> { new_connection_with_socket() } /// Variant of [`new_connection`] that allows specifying a socket type to use /// for async handling #[allow(clippy::type_complexity)] pub fn new_connection_with_socket() -> io::Result<( Connection, GenetlinkHandle, UnboundedReceiver<(NetlinkMessage, SocketAddr)>, )> where S: AsyncSocket, { let (conn, handle, messages) = netlink_proto::new_connection_with_socket(NETLINK_GENERIC)?; Ok((conn, GenetlinkHandle::new(handle), messages)) } genetlink-0.2.5/src/error.rs000064400000000000000000000016611046102023000141020ustar 00000000000000// SPDX-License-Identifier: MIT use crate::message::RawGenlMessage; /// Error type of genetlink #[derive(Debug, Error)] pub enum GenetlinkError { #[error("Failed to send netlink request")] ProtocolError(#[from] netlink_proto::Error), #[error("Failed to decode generic packet")] DecodeError(#[from] netlink_packet_utils::DecodeError), #[error("Netlink error message: {0}")] NetlinkError(std::io::Error), #[error("Cannot find specified netlink attribute: {0}")] AttributeNotFound(String), #[error("Desire netlink message type not received")] NoMessageReceived, } // Since `netlink_packet_core::error::ErrorMessage` doesn't impl `Error` trait, // it need to convert to `std::io::Error` here impl From for GenetlinkError { fn from(err_msg: netlink_packet_core::error::ErrorMessage) -> Self { Self::NetlinkError(err_msg.to_io()) } } genetlink-0.2.5/src/handle.rs000064400000000000000000000127341046102023000142070ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{ error::GenetlinkError, message::{map_from_rawgenlmsg, map_to_rawgenlmsg, RawGenlMessage}, resolver::Resolver, }; use futures::{lock::Mutex, Stream, StreamExt}; use netlink_packet_core::{NetlinkMessage, NetlinkPayload}; use netlink_packet_generic::{GenlFamily, GenlHeader, GenlMessage}; use netlink_packet_utils::{DecodeError, Emitable, ParseableParametrized}; use netlink_proto::{sys::SocketAddr, ConnectionHandle}; use std::{fmt::Debug, sync::Arc}; /// The generic netlink connection handle /// /// The handle is used to send messages to the connection. It also resolves /// the family id automatically before sending messages. /// /// # Family id resolving /// There is a resolver with cache inside each connection. When you send generic /// netlink message, the handle resolves and fills the family id into the /// message. /// /// Since the resolver is created in /// [`new_connection()`](crate::new_connection), the cache state wouldn't share /// between different connections. /// /// P.s. The cloned handles use the same connection with the original handle. /// So, they share the same cache state. /// /// # Detailed process of sending generic messages /// 1. Check if the message's family id is resolved. If yes, jump to step 6. /// 2. Query the family id using the builtin resolver. /// 3. If the id is in the cache, returning the id in the cache and skip step 4. /// 4. The resolver sends `CTRL_CMD_GETFAMILY` request to get the id and records /// it in the cache. 5. fill the family id using /// [`GenlMessage::set_resolved_family_id()`]. 6. Serialize the payload to /// [`RawGenlMessage`]. 7. Send it through the connection. /// - The family id filled into `message_type` field in /// [`NetlinkMessage::finalize()`]. /// 8. In the response stream, deserialize the payload back to /// [`GenlMessage`]. #[derive(Clone, Debug)] pub struct GenetlinkHandle { handle: ConnectionHandle, resolver: Arc>, } impl GenetlinkHandle { pub(crate) fn new(handle: ConnectionHandle) -> Self { Self { handle, resolver: Arc::new(Mutex::new(Resolver::new())), } } /// Resolve the family id of the given [`GenlFamily`]. pub async fn resolve_family_id(&self) -> Result where F: GenlFamily, { self.resolver .lock() .await .query_family_id(self, F::family_name()) .await } /// Clear the resolver's fanily id cache pub async fn clear_family_id_cache(&self) { self.resolver.lock().await.clear_cache(); } /// Send the generic netlink message and get the response stream /// /// The function resolves the family id before sending the request. If the /// resolving process is failed, the function would return an error. pub async fn request( &mut self, mut message: NetlinkMessage>, ) -> Result< impl Stream>, DecodeError>>, GenetlinkError, > where F: GenlFamily + Emitable + ParseableParametrized<[u8], GenlHeader> + Debug, { self.resolve_message_family_id(&mut message).await?; self.send_request(message) } /// Send the request without resolving family id /// /// This function is identical to [`request()`](Self::request) but it /// doesn't resolve the family id for you. pub fn send_request( &mut self, message: NetlinkMessage>, ) -> Result< impl Stream>, DecodeError>>, GenetlinkError, > where F: GenlFamily + Emitable + ParseableParametrized<[u8], GenlHeader> + Debug, { let raw_msg = map_to_rawgenlmsg(message); let stream = self.handle.request(raw_msg, SocketAddr::new(0, 0))?; Ok(stream.map(map_from_rawgenlmsg)) } /// Send the generic netlink message without returning the response stream pub async fn notify( &mut self, mut message: NetlinkMessage>, ) -> Result<(), GenetlinkError> where F: GenlFamily + Emitable + ParseableParametrized<[u8], GenlHeader> + Debug, { self.resolve_message_family_id(&mut message).await?; self.send_notify(message) } /// Send the notify without resolving family id pub fn send_notify( &mut self, message: NetlinkMessage>, ) -> Result<(), GenetlinkError> where F: GenlFamily + Emitable + ParseableParametrized<[u8], GenlHeader> + Debug, { let raw_msg = map_to_rawgenlmsg(message); self.handle.notify(raw_msg, SocketAddr::new(0, 0))?; Ok(()) } async fn resolve_message_family_id( &mut self, message: &mut NetlinkMessage>, ) -> Result<(), GenetlinkError> where F: GenlFamily + Debug, { if let NetlinkPayload::InnerMessage(genlmsg) = &mut message.payload { if genlmsg.family_id() == 0 { // The family id is not resolved // Resolve it before send it let id = self.resolve_family_id::().await?; genlmsg.set_resolved_family_id(id); } } Ok(()) } } genetlink-0.2.5/src/lib.rs000064400000000000000000000005031046102023000135110ustar 00000000000000// SPDX-License-Identifier: MIT #[macro_use] extern crate thiserror; mod connection; mod error; mod handle; pub mod message; mod resolver; #[cfg(feature = "tokio_socket")] pub use connection::new_connection; pub use connection::new_connection_with_socket; pub use error::GenetlinkError; pub use handle::GenetlinkHandle; genetlink-0.2.5/src/message.rs000064400000000000000000000145071046102023000144000ustar 00000000000000// SPDX-License-Identifier: MIT //! Raw generic netlink payload message //! //! # Design //! Since we use generic type to represent different generic family's message //! type, and it is not easy to create a underlying //! [`netlink_proto::new_connection()`] with trait object to multiplex different //! generic netlink family's message. //! //! Therefore, I decided to serialize the generic type payload into bytes before //! sending to the underlying connection. The [`RawGenlMessage`] is meant for //! this. //! //! This special message doesn't use generic type and its payload is `Vec`. //! Therefore, its type is easier to use. //! //! Another advantage is that it can let users know when the generic netlink //! payload fails to decode instead of just dropping the messages. //! (`netlink_proto` would drop messages if they fails to decode.) //! I think this can help developers debug their deserializing implementation. use netlink_packet_core::{ NetlinkDeserializable, NetlinkHeader, NetlinkMessage, NetlinkPayload, NetlinkSerializable, }; use netlink_packet_generic::{GenlBuffer, GenlFamily, GenlHeader, GenlMessage}; use netlink_packet_utils::{ DecodeError, Emitable, Parseable, ParseableParametrized, }; use std::fmt::Debug; /// Message type to hold serialized generic netlink payload /// /// **Note** This message type is not intend to be used by normal users, unless /// you need to use the `UnboundedReceiver<(NetlinkMessage, /// SocketAddr)>` return by [`new_connection()`](crate::new_connection) #[derive(Clone, Debug, PartialEq, Eq)] pub struct RawGenlMessage { pub header: GenlHeader, pub payload: Vec, pub family_id: u16, } impl RawGenlMessage { /// Construct the message pub fn new(header: GenlHeader, payload: Vec, family_id: u16) -> Self { Self { header, payload, family_id, } } /// Consume this message and return its header and payload pub fn into_parts(self) -> (GenlHeader, Vec) { (self.header, self.payload) } /// Serialize the generic netlink payload into raw bytes pub fn from_genlmsg(genlmsg: GenlMessage) -> Self where F: GenlFamily + Emitable + Debug, { let mut payload_buf = vec![0u8; genlmsg.payload.buffer_len()]; genlmsg.payload.emit(&mut payload_buf); Self { header: genlmsg.header, payload: payload_buf, family_id: genlmsg.family_id(), } } /// Try to deserialize the generic netlink payload from raw bytes pub fn parse_into_genlmsg(&self) -> Result, DecodeError> where F: GenlFamily + ParseableParametrized<[u8], GenlHeader> + Debug, { let inner = F::parse_with_param(&self.payload, self.header)?; Ok(GenlMessage::new(self.header, inner, self.family_id)) } } impl Emitable for RawGenlMessage { fn buffer_len(&self) -> usize { self.header.buffer_len() + self.payload.len() } fn emit(&self, buffer: &mut [u8]) { self.header.emit(buffer); let buffer = &mut buffer[self.header.buffer_len()..]; buffer.copy_from_slice(&self.payload); } } impl<'a, T> ParseableParametrized, u16> for RawGenlMessage where T: AsRef<[u8]> + ?Sized, { fn parse_with_param( buf: &GenlBuffer<&'a T>, message_type: u16, ) -> Result { let header = GenlHeader::parse(buf)?; let payload_buf = buf.payload(); Ok(RawGenlMessage::new( header, payload_buf.to_vec(), message_type, )) } } impl NetlinkSerializable for RawGenlMessage { fn message_type(&self) -> u16 { self.family_id } fn buffer_len(&self) -> usize { ::buffer_len(self) } fn serialize(&self, buffer: &mut [u8]) { self.emit(buffer) } } impl NetlinkDeserializable for RawGenlMessage { type Error = DecodeError; fn deserialize( header: &NetlinkHeader, payload: &[u8], ) -> Result { let buffer = GenlBuffer::new_checked(payload)?; RawGenlMessage::parse_with_param(&buffer, header.message_type) } } impl From for NetlinkPayload { fn from(message: RawGenlMessage) -> Self { NetlinkPayload::InnerMessage(message) } } /// Helper function to map the [`NetlinkPayload`] types in [`NetlinkMessage`] /// and serialize the generic netlink payload into raw bytes. pub fn map_to_rawgenlmsg( message: NetlinkMessage>, ) -> NetlinkMessage where F: GenlFamily + Emitable + Debug, { let raw_payload = match message.payload { NetlinkPayload::InnerMessage(genlmsg) => { NetlinkPayload::InnerMessage(RawGenlMessage::from_genlmsg(genlmsg)) } NetlinkPayload::Done(i) => NetlinkPayload::Done(i), NetlinkPayload::Error(i) => NetlinkPayload::Error(i), NetlinkPayload::Noop => NetlinkPayload::Noop, NetlinkPayload::Overrun(i) => NetlinkPayload::Overrun(i), i => { log::warn!( "map_from_rawgenlmsg(): Unexpected NetlinkPayload {:?}", i ); NetlinkPayload::Noop } }; NetlinkMessage::new(message.header, raw_payload) } /// Helper function to map the [`NetlinkPayload`] types in [`NetlinkMessage`] /// and try to deserialize the generic netlink payload from raw bytes. pub fn map_from_rawgenlmsg( raw_msg: NetlinkMessage, ) -> Result>, DecodeError> where F: GenlFamily + ParseableParametrized<[u8], GenlHeader> + Debug, { let payload = match raw_msg.payload { NetlinkPayload::InnerMessage(raw_genlmsg) => { NetlinkPayload::InnerMessage(raw_genlmsg.parse_into_genlmsg()?) } NetlinkPayload::Done(i) => NetlinkPayload::Done(i), NetlinkPayload::Error(i) => NetlinkPayload::Error(i), NetlinkPayload::Noop => NetlinkPayload::Noop, NetlinkPayload::Overrun(i) => NetlinkPayload::Overrun(i), i => { log::warn!( "map_from_rawgenlmsg(): Unexpected NetlinkPayload {:?}", i ); NetlinkPayload::Noop } }; Ok(NetlinkMessage::new(raw_msg.header, payload)) } genetlink-0.2.5/src/resolver.rs000064400000000000000000000120341046102023000146060ustar 00000000000000// SPDX-License-Identifier: MIT use crate::{error::GenetlinkError, GenetlinkHandle}; use futures::{future::Either, StreamExt}; use netlink_packet_core::{NetlinkMessage, NetlinkPayload, NLM_F_REQUEST}; use netlink_packet_generic::{ ctrl::{nlas::GenlCtrlAttrs, GenlCtrl, GenlCtrlCmd}, GenlMessage, }; use std::{collections::HashMap, future::Future}; #[derive(Clone, Debug, Default)] pub struct Resolver { cache: HashMap<&'static str, u16>, } impl Resolver { pub fn new() -> Self { Self { cache: HashMap::new(), } } pub fn get_cache_by_name(&self, family_name: &str) -> Option { self.cache.get(family_name).copied() } pub fn query_family_id( &mut self, handle: &GenetlinkHandle, family_name: &'static str, ) -> impl Future> + '_ { if let Some(id) = self.get_cache_by_name(family_name) { Either::Left(futures::future::ready(Ok(id))) } else { let mut handle = handle.clone(); Either::Right(async move { let mut genlmsg: GenlMessage = GenlMessage::from_payload(GenlCtrl { cmd: GenlCtrlCmd::GetFamily, nlas: vec![GenlCtrlAttrs::FamilyName( family_name.to_owned(), )], }); genlmsg.finalize(); // We don't have to set family id here, since nlctrl has static // family id (0x10) let mut nlmsg = NetlinkMessage::from(genlmsg); nlmsg.header.flags = NLM_F_REQUEST; nlmsg.finalize(); let mut res = handle.send_request(nlmsg)?; while let Some(result) = res.next().await { let rx_packet = result?; match rx_packet.payload { NetlinkPayload::InnerMessage(genlmsg) => { let family_id = genlmsg .payload .nlas .iter() .find_map(|nla| { if let GenlCtrlAttrs::FamilyId(id) = nla { Some(*id) } else { None } }) .ok_or_else(|| { GenetlinkError::AttributeNotFound( "CTRL_ATTR_FAMILY_ID".to_owned(), ) })?; self.cache.insert(family_name, family_id); return Ok(family_id); } NetlinkPayload::Error(e) => return Err(e.into()), _ => (), } } Err(GenetlinkError::NoMessageReceived) }) } } pub fn clear_cache(&mut self) { self.cache.clear(); } } #[cfg(test)] mod test { use super::*; use crate::new_connection; use std::io::ErrorKind; #[tokio::test] async fn test_resolver_nlctrl() { let (conn, handle, _) = new_connection().unwrap(); tokio::spawn(conn); let mut resolver = Resolver::new(); // nlctrl should always be 0x10 let nlctrl_fid = resolver.query_family_id(&handle, "nlctrl").await.unwrap(); assert_eq!(nlctrl_fid, 0x10); } const TEST_FAMILIES: &[&str] = &[ "devlink", "ethtool", "acpi_event", "tcp_metrics", "TASKSTATS", "nl80211", ]; #[tokio::test] async fn test_resolver_cache() { let (conn, handle, _) = new_connection().unwrap(); tokio::spawn(conn); let mut resolver = Resolver::new(); // Test if family id cached for name in TEST_FAMILIES.iter().copied() { let id = resolver .query_family_id(&handle, name) .await .or_else(|e| { if let GenetlinkError::NetlinkError(io_err) = &e { if io_err.kind() == ErrorKind::NotFound { // Ignore non exist entries Ok(0) } else { Err(e) } } else { Err(e) } }) .unwrap(); if id == 0 { log::warn!( "Generic family \"{name}\" not exist or not loaded \ in this environment. Ignored." ); continue; } let cache = resolver.get_cache_by_name(name).unwrap(); assert_eq!(id, cache); log::warn!("{:?}", (name, cache)); } } }