├── .github └── workflows │ ├── build-and-test.yml │ ├── formatting.yml │ ├── git-commit-message-style.yml │ └── linting.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── nftnl-sys ├── Cargo.toml ├── README.md ├── build.rs ├── generate_bindings.sh ├── libnftnl.h └── src │ ├── lib.rs │ ├── nftnl_1_0_6.rs │ ├── nftnl_1_0_7.rs │ ├── nftnl_1_0_8.rs │ ├── nftnl_1_0_9.rs │ ├── nftnl_1_1_0.rs │ ├── nftnl_1_1_1.rs │ └── nftnl_1_1_2.rs ├── nftnl ├── Cargo.toml ├── examples │ ├── add-ingress-rule.rs │ ├── add-rules.rs │ └── filter-ethernet.rs └── src │ ├── batch.rs │ ├── chain.rs │ ├── expr │ ├── bitwise.rs │ ├── cmp.rs │ ├── counter.rs │ ├── ct.rs │ ├── immediate.rs │ ├── lookup.rs │ ├── masquerade.rs │ ├── meta.rs │ ├── mod.rs │ ├── nat.rs │ ├── payload.rs │ └── verdict.rs │ ├── lib.rs │ ├── rule.rs │ ├── set.rs │ └── table.rs └── rustfmt.toml /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build and test 3 | on: 4 | pull_request: 5 | paths: 6 | - .github/workflows/build-and-test.yml 7 | - '**/*.rs' 8 | - Cargo.toml 9 | - Cargo.lock 10 | workflow_dispatch: 11 | 12 | env: 13 | CARGO_TERM_COLOR: always 14 | RUSTFLAGS: --deny warnings 15 | 16 | jobs: 17 | build-and-test: 18 | strategy: 19 | matrix: 20 | # Keep MSRV in sync with rust-version in Cargo.toml 21 | rust: [stable, beta, nightly, 1.63.0] 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Install build dependencies 25 | run: | 26 | sudo apt-get update 27 | sudo apt-get install -y libnftnl-dev libmnl-dev 28 | 29 | - uses: actions/checkout@v4 30 | 31 | - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #v1.0.7 32 | with: 33 | toolchain: ${{ matrix.rust }} 34 | profile: minimal 35 | default: true 36 | 37 | - name: Build 38 | run: cargo build --all-targets --locked 39 | 40 | - name: Test 41 | run: cargo test --locked 42 | 43 | # Make sure documentation builds without warnings (broken links etc) 44 | - name: Generate documentation 45 | if: matrix.rust == 'stable' 46 | run: RUSTDOCFLAGS="--deny warnings" cargo doc 47 | 48 | # Make sure the library builds with all dependencies downgraded to their 49 | # oldest versions allowed by the semver spec. This ensures we have not 50 | # under-specified any dependency 51 | minimal-versions: 52 | runs-on: ubuntu-latest 53 | steps: 54 | - name: Install build dependencies 55 | run: | 56 | sudo apt-get update 57 | sudo apt-get install -y libnftnl-dev libmnl-dev 58 | 59 | - uses: actions/checkout@v4 60 | 61 | - name: Install stable Rust 62 | uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #v1.0.7 63 | with: 64 | toolchain: stable 65 | profile: minimal 66 | 67 | - name: Install nightly Rust 68 | uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #v1.0.7 69 | with: 70 | toolchain: nightly 71 | profile: minimal 72 | 73 | - name: Downgrade dependencies to minimal versions 74 | run: cargo +nightly update -Z minimal-versions 75 | 76 | - name: Compile with minimal versions 77 | run: cargo +stable build --all-targets --locked 78 | -------------------------------------------------------------------------------- /.github/workflows/formatting.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rust formatting 3 | on: 4 | pull_request: 5 | paths: 6 | - .github/workflows/formatting.yml 7 | - '**/*.rs' 8 | workflow_dispatch: 9 | jobs: 10 | check-formatting: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #v1.0.7 16 | with: 17 | toolchain: stable 18 | profile: minimal 19 | components: rustfmt 20 | default: true 21 | 22 | - name: Check formatting 23 | run: | 24 | rustfmt --version 25 | cargo fmt -- --check 26 | -------------------------------------------------------------------------------- /.github/workflows/git-commit-message-style.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Git - Check commit message style 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | check-commit-message-style: 9 | name: Check commit message style 10 | runs-on: ubuntu-latest 11 | steps: 12 | # Make sure there are no whitespaces other than space, tab and newline in a commit message. 13 | - name: Check for unicode whitespaces 14 | uses: gsactions/commit-message-checker@16fa2d5de096ae0d35626443bcd24f1e756cafee #v2.0.0 15 | with: 16 | # Pattern matches strings not containing weird unicode whitespace/separator characters 17 | # \P{Z} = All non-whitespace characters (the u-flag is needed to enable \P{Z}) 18 | # [ \t\n] = Allowed whitespace characters 19 | pattern: '^(\P{Z}|[ \t\n])+$' 20 | flags: 'u' 21 | error: 'Detected unicode whitespace character in commit message.' 22 | checkAllCommitMessages: 'true' # optional: this checks all commits associated with a pull request 23 | accessToken: ${{ secrets.GITHUB_TOKEN }} # only required if checkAllCommitMessages is true 24 | 25 | # Git commit messages should follow these guidelines: https://cbea.ms/git-commit/ 26 | - name: Check against guidelines 27 | uses: mristin/opinionated-commit-message@f3b9cec249cabffbae7cd564542fd302cc576827 #v3.1.1 28 | with: 29 | # Commit messages are allowed to be subject only, no body 30 | allow-one-liners: 'true' 31 | # This action defaults to 50 char subjects, but 72 is fine. 32 | max-subject-line-length: '72' 33 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rust linting 3 | on: 4 | pull_request: 5 | paths: 6 | - .github/workflows/linting.yml 7 | - '**/*.rs' 8 | - Cargo.toml 9 | - Cargo.lock 10 | workflow_dispatch: 11 | jobs: 12 | clippy-linting: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Install build dependencies 16 | run: | 17 | sudo apt-get update 18 | sudo apt-get install -y libnftnl-dev libmnl-dev 19 | 20 | - uses: actions/checkout@v4 21 | 22 | - uses: actions-rs/toolchain@v1.0.6 23 | with: 24 | toolchain: stable 25 | profile: minimal 26 | components: clippy 27 | default: true 28 | 29 | - name: Clippy check 30 | env: 31 | RUSTFLAGS: --deny warnings 32 | run: cargo clippy --locked --all-targets 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ### Categories each change fall into 8 | 9 | * **Added**: for new features. 10 | * **Changed**: for changes in existing functionality. 11 | * **Deprecated**: for soon-to-be removed features. 12 | * **Removed**: for now removed features. 13 | * **Fixed**: for any bug fixes. 14 | * **Security**: in case of vulnerabilities. 15 | 16 | 17 | ## [Unreleased] 18 | 19 | 20 | ## [0.7.0] - 2024-09-19 21 | ### Added 22 | - Implement `Default` for `nftnl::batch::Batch`. 23 | - Add support for Raw payload expressions. 24 | 25 | ### Changed 26 | - Upgrade crates to Rust 2021 edition. 27 | - Specify MSRV for `nftnl` and `nftnl-sys` to version 1.56.0. 28 | - Upgrade `bitflags` dependency to version 2.6.0. 29 | - Fix minimal allowed version of `mnl` to 0.2.2. 30 | - Remove the `error-derive` dependency. `std::error::Error` is now implemented manually for 31 | `NetlinkError`. 32 | 33 | ### Removed 34 | - Remove `Ord` and `PartialOrd` implementation on `States` and `ConntrackStatus`. 35 | 36 | ### Fixed 37 | - Fix building documentation on docs.rs by not linking to `libmnl` and `libmnl` during documentation 38 | generation. 39 | - Fix compile errors by removing `expect` statments from `nft_set` macro 40 | 41 | 42 | ## [0.6.2] - 2022-02-11 43 | ### Added 44 | - Add `ct status` to load the conntrack status, and add conntrack status bitflags. 45 | 46 | ### Fixed 47 | - Specify dependency versions more exactly to allow building with minimal versions 48 | of the entire dependency tree. 49 | 50 | 51 | ## [0.6.1] - 2021-02-04 52 | ### Changed 53 | - Upgrade the err-derive dependency to 0.3.0. 54 | 55 | 56 | ## [0.6.0] - 2020-11-23 57 | ### Added 58 | - Implement Send+Sync for Table, Chain, Rule, Batch and Iter (batch iterator). 59 | - Add `Nat` expression allowing SNat and DNat rules. 60 | 61 | ### Changed 62 | - Add `Register` enum and a register field to the `Immediate` expression. Allowing control 63 | over which netfilter register the immediate data is loaded into 64 | 65 | ### Fixed 66 | - Fix memory leak in `table::get_tables_cb`. 67 | 68 | 69 | ## [0.5.0] - 2020-06-04 70 | ### Added 71 | - Add support for matching on socket UID and socket GID in `Meta` expressions. 72 | 73 | ### Changed 74 | - Mark `Meta` and many payload enums as `#[non_exhaustive]`. Allows adding more expressions 75 | without a breaking release in the future. 76 | - Increase minimum supported rust version to 1.40 due to `#[non_exhaustive]`. 77 | 78 | 79 | ## [0.4.0] - 2020-05-27 80 | ### Added 81 | - Add `Reject` verdict for responding with ICMP packets or TCP RST to the origin. 82 | 83 | 84 | ## [0.3.0] - 2020-04-20 85 | ### Added 86 | - Add `ChainType` and allow setting a chain to either filter, route or nat type. 87 | - Add support for reading and setting marks in the `Meta` and `Conntrack` expressions. 88 | - Add support for reading the cgroup via the `Meta` expression. 89 | - Add `Immediate` expression type that can load data into the registers. 90 | - Add support for masquerading. 91 | - Implement `Debug` for `Chain`. 92 | 93 | ### Changed 94 | - Change `get_tables_nlmsg` to include all tables, not only inet tables, 95 | but also arp, ip, ip6, bridge etc. 96 | 97 | ### Fixed 98 | - Fix compilation errors on ARM64 platforms. 99 | - Set `NFTNL_CHAIN_FAMILY` for chains and other fixes making the library compatible 100 | with older kernels. 101 | 102 | ## [0.2.1] - 2019-09-23 103 | ### Added 104 | - Add support for checking ICMPv6 header fields. 105 | 106 | 107 | ## [0.2.0] - 2019-04-05 108 | ### Added 109 | - Add `add-get-tables-request` that can create requests to enumerate tables. 110 | - Add bindings to `libnftnl-1.1.2`. 111 | 112 | ### Changed 113 | - Upgrade crates to Rust 2018 edition. 114 | - Remove the `error-chain` dependency. Now aborts on allocation error. 115 | 116 | 117 | ## [0.1.0] - 2018-09-10 118 | ### Added 119 | - Bindings to `libnftnl` versions `1.0.6` through `1.1.1` 120 | - Initial safe abstraction. Support for batches, tables, chains, rules and sets. 121 | All with a limited set of expression types. 122 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "bitflags" 7 | version = "2.6.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 10 | 11 | [[package]] 12 | name = "cfg-if" 13 | version = "1.0.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 16 | 17 | [[package]] 18 | name = "ipnetwork" 19 | version = "0.20.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" 22 | dependencies = [ 23 | "serde", 24 | ] 25 | 26 | [[package]] 27 | name = "libc" 28 | version = "0.2.166" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" 31 | 32 | [[package]] 33 | name = "log" 34 | version = "0.4.18" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" 37 | 38 | [[package]] 39 | name = "mnl" 40 | version = "0.2.2" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "d1a5469630da93e1813bb257964c0ccee3b26b6879dd858039ddec35cc8681ed" 43 | dependencies = [ 44 | "libc", 45 | "log", 46 | "mnl-sys", 47 | ] 48 | 49 | [[package]] 50 | name = "mnl-sys" 51 | version = "0.2.1" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "9750685b201e1ecfaaf7aa5d0387829170fa565989cc481b49080aa155f70457" 54 | dependencies = [ 55 | "libc", 56 | "pkg-config", 57 | ] 58 | 59 | [[package]] 60 | name = "nftnl" 61 | version = "0.7.0" 62 | dependencies = [ 63 | "bitflags", 64 | "ipnetwork", 65 | "log", 66 | "mnl", 67 | "nftnl-sys", 68 | ] 69 | 70 | [[package]] 71 | name = "nftnl-sys" 72 | version = "0.6.2" 73 | dependencies = [ 74 | "cfg-if", 75 | "libc", 76 | "pkg-config", 77 | ] 78 | 79 | [[package]] 80 | name = "pkg-config" 81 | version = "0.3.19" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 84 | 85 | [[package]] 86 | name = "serde" 87 | version = "1.0.185" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" 90 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["nftnl-sys", "nftnl"] 4 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Amagicom AB 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nftnl 2 | 3 | Safe abstraction for [`libnftnl`]. Provides low-level userspace access to the in-kernel 4 | nf_tables subsystem. See [`nftnl-sys`] for the low level FFI bindings to the C library. 5 | 6 | Can be used to create and remove tables, chains, sets and rules from the nftables firewall, 7 | the successor to iptables. 8 | 9 | This library currently has quite rough edges and does not make adding and removing netfilter 10 | entries super easy and elegant. That is partly because the library needs more work, but also 11 | partly because nftables is super low level and extremely customizable, making it hard, and 12 | probably wrong, to try and create a too simple/limited wrapper. See examples for inspiration. 13 | One can also look at how the original project this crate was developed to support uses it: 14 | [Mullvad VPN app](https://github.com/mullvad/mullvadvpn-app) 15 | 16 | Understanding how to use [`libnftnl`] and implementing this crate has mostly been done by 17 | reading the source code for the [`nftables`] program and attaching debuggers to the `nft` 18 | binary. Since the implementation is mostly based on trial and error, there might of course be 19 | a number of places where the underlying library is used in an invalid or not intended way. 20 | Large portions of [`libnftnl`] are also not covered yet. Contributions are welcome! 21 | 22 | ## Selecting version of `libnftnl` 23 | 24 | See the documentation for the corresponding sys crate for details: [`nftnl-sys`] 25 | This crate has the same features as the sys crate, and selecting version works the same. 26 | 27 | [`libnftnl`]: https://netfilter.org/projects/libnftnl/ 28 | [`nftables`]: https://netfilter.org/projects/nftables/ 29 | [`nftnl-sys`]: https://crates.io/crates/nftnl-sys 30 | 31 | License: MIT/Apache-2.0 32 | -------------------------------------------------------------------------------- /nftnl-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nftnl-sys" 3 | version = "0.6.2" 4 | authors = ["Mullvad VPN"] 5 | license = "MIT OR Apache-2.0" 6 | description = "Low level FFI bindings to libnftnl. Provides low-level userspace access to the in-kernel nf_tables subsystem" 7 | repository = "https://github.com/mullvad/nftnl-rs" 8 | readme = "README.md" 9 | keywords = ["nftables", "nft", "firewall", "iptables", "netfilter"] 10 | categories = ["network-programming", "os::unix-apis", "external-ffi-bindings", "no-std"] 11 | edition = "2021" 12 | rust-version = "1.63.0" 13 | 14 | 15 | [features] 16 | nftnl-1-0-7 = [] 17 | nftnl-1-0-8 = ["nftnl-1-0-7"] 18 | nftnl-1-0-9 = ["nftnl-1-0-8"] 19 | nftnl-1-1-0 = ["nftnl-1-0-9"] 20 | nftnl-1-1-1 = ["nftnl-1-1-0"] 21 | nftnl-1-1-2 = ["nftnl-1-1-1"] 22 | 23 | [dependencies] 24 | cfg-if = "1.0" 25 | libc = "0.2.166" 26 | 27 | [build-dependencies] 28 | cfg-if = "1.0" 29 | pkg-config = "0.3.19" 30 | -------------------------------------------------------------------------------- /nftnl-sys/README.md: -------------------------------------------------------------------------------- 1 | # nftnl-sys 2 | 3 | Low level FFI bindings to [`libnftnl`], a userspace library providing a low-level netlink 4 | programming interface (API) to the in-kernel nf_tables subsystem. 5 | 6 | See [`nftnl`] for a higher level safe abstraction. 7 | 8 | ## Linking to libmnl and libnftnl 9 | 10 | By default this crate uses pkg-config to find and link to its C dependencies, [`libmnl`] and 11 | [`libnftnl`]. To manually configure where to look for these libraries, set the environment 12 | variables `LIBMNL_LIB_DIR` and `LIBNFTNL_LIB_DIR` to point to the directories where `libmnl.so` 13 | (or `libmnl.a`) and `libnftnl.so` (or `libnftnl.a`) reside. 14 | 15 | ## Selecting version of `libnftnl` 16 | 17 | This crate has bindings for most versions of [`libnftnl`]. All bindings are generated by 18 | [`bindgen`] via the `generate_bindings.sh` script in this repository. 19 | 20 | Only one version of `libnftnl` can be exposed via this crate. By default the crate exports the 21 | bindings for the oldest supported version (`libnftnl-1.0.6`). To get newer versions activate the 22 | corresponding features. See `Cargo.toml` for available features/versions. 23 | 24 | So for example, to get bindings to `libnftnl-1.0.9` depend on this crate like this: 25 | ```toml 26 | [dependencies] 27 | nftnl-sys = { version = "0.1", features = ["nftnl-1-0-9"] } 28 | ``` 29 | 30 | [`libnftnl`]: https://netfilter.org/projects/libnftnl/ 31 | [`libmnl`]: https://netfilter.org/projects/libmnl/ 32 | [`nftnl`]: https://crates.io/crates/nftnl 33 | [`bindgen`]: https://crates.io/crates/bindgen 34 | 35 | License: MIT/Apache-2.0 36 | -------------------------------------------------------------------------------- /nftnl-sys/build.rs: -------------------------------------------------------------------------------- 1 | extern crate pkg_config; 2 | 3 | use std::{env, path::PathBuf}; 4 | 5 | cfg_if::cfg_if! { 6 | if #[cfg(feature = "nftnl-1-1-2")] { 7 | const MIN_VERSION: &str = "1.1.2"; 8 | } else if #[cfg(feature = "nftnl-1-1-1")] { 9 | const MIN_VERSION: &str = "1.1.1"; 10 | } else if #[cfg(feature = "nftnl-1-1-0")] { 11 | const MIN_VERSION: &str = "1.1.0"; 12 | } else if #[cfg(feature = "nftnl-1-0-9")] { 13 | const MIN_VERSION: &str = "1.0.9"; 14 | } else if #[cfg(feature = "nftnl-1-0-8")] { 15 | const MIN_VERSION: &str = "1.0.8"; 16 | } else if #[cfg(feature = "nftnl-1-0-7")] { 17 | const MIN_VERSION: &str = "1.0.7"; 18 | } else { 19 | const MIN_VERSION: &str = "1.0.6"; 20 | } 21 | } 22 | 23 | fn get_env(var: &'static str) -> Option { 24 | println!("cargo:rerun-if-env-changed={}", var); 25 | env::var_os(var).map(PathBuf::from) 26 | } 27 | 28 | fn main() { 29 | // Do NOT link when building documentation on docs.rs. The native libraries are not 30 | // present on their build machines and just makes the compilation fail. Documentation 31 | // generation will work without linking. 32 | if std::env::var("DOCS_RS").is_ok() { 33 | return; 34 | } 35 | 36 | if let Some(lib_dir) = get_env("LIBNFTNL_LIB_DIR") { 37 | if !lib_dir.is_dir() { 38 | panic!( 39 | "libnftnl library directory does not exist: {}", 40 | lib_dir.display() 41 | ); 42 | } 43 | println!("cargo:rustc-link-search=native={}", lib_dir.display()); 44 | println!("cargo:rustc-link-lib=nftnl"); 45 | } else { 46 | // Trying with pkg-config instead 47 | println!("Minimum libnftnl version: {}", MIN_VERSION); 48 | pkg_config::Config::new() 49 | .atleast_version(MIN_VERSION) 50 | .probe("libnftnl") 51 | .unwrap(); 52 | } 53 | 54 | if let Some(lib_dir) = get_env("LIBMNL_LIB_DIR") { 55 | if !lib_dir.is_dir() { 56 | panic!( 57 | "libmnl library directory does not exist: {}", 58 | lib_dir.display() 59 | ); 60 | } 61 | println!("cargo:rustc-link-search=native={}", lib_dir.display()); 62 | println!("cargo:rustc-link-lib=mnl"); 63 | } else { 64 | // Trying with pkg-config instead 65 | pkg_config::Config::new() 66 | .atleast_version("1.0.0") 67 | .probe("libmnl") 68 | .unwrap(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /nftnl-sys/generate_bindings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # give libnftnl C library dir as first argument and output binding as second. 4 | # Example: 5 | # $ ./generate_bindings.sh ../../libnftnl-1.0.8 src/nftnl_1_0_8.rs 6 | 7 | set -ue 8 | 9 | LIBNFTNL_PATH=$1 10 | BINDING_PATH=$2 11 | 12 | echo "Writing the result to $BINDING_PATH" 13 | 14 | bindgen \ 15 | --no-doc-comments \ 16 | --use-core \ 17 | --no-prepend-enum-name \ 18 | --whitelist-function '^nftnl_.+$' \ 19 | --whitelist-type '^nftnl_.+$' \ 20 | --whitelist-var '^nftnl_.+$' \ 21 | --whitelist-var '^NFTNL_.+$' \ 22 | --blacklist-type '(FILE|iovec)' \ 23 | --blacklist-type '^_IO_.+$' \ 24 | --blacklist-type '^__.+$' \ 25 | --blacklist-type 'nlmsghdr' \ 26 | --raw-line 'use libc::{c_char, c_int, c_void, iovec, nlmsghdr, FILE};' \ 27 | --raw-line 'use core::option::Option;' \ 28 | --ctypes-prefix 'libc' \ 29 | -o $BINDING_PATH \ 30 | libnftnl.h --\ 31 | -I$LIBNFTNL_PATH/include 32 | 33 | # Tidy up and correct things I could not manage to configure bindgen to do for me 34 | sed -i 's/libc::\(c_[a-z]*\)/\1/g' $BINDING_PATH 35 | sed -i 's/::core::option::Option/Option/g' $BINDING_PATH 36 | sed -i 's/_bindgen_ty_[0-9]\+/u32/g' $BINDING_PATH 37 | sed -i 's/pub type u32 = u32;//g' $BINDING_PATH 38 | sed -i '/#\[derive(Debug, Copy, Clone)\]/d' $BINDING_PATH 39 | 40 | # Change struct bodies to (c_void); 41 | # Search regex: {\n +_unused: \[u8; 0],\n} 42 | # Replace string: (c_void);\n 43 | sed -i -e '/^pub struct .* {$/ { 44 | N;N 45 | s/ {\n *_unused: \[u8; 0\],\n}/(c_void);\n/ 46 | }' "$BINDING_PATH" 47 | 48 | 49 | # Remove all }\nextern "C" { to condense code a bit 50 | # Search regex: }\nextern "C" { 51 | # Replace string: 52 | sed -i -e '/^extern "C" {$/ { 53 | :loop 54 | n 55 | /^}$/! b loop 56 | /^}$/ { 57 | N 58 | t reset_condition_flags 59 | :reset_condition_flags 60 | s/}\nextern "C" {// 61 | t loop 62 | } 63 | }' "$BINDING_PATH" 64 | 65 | # Add bindgen version to comment at start of file 66 | sed -i "1s/bindgen/$(bindgen --version)/" $BINDING_PATH 67 | 68 | rustfmt $BINDING_PATH 69 | -------------------------------------------------------------------------------- /nftnl-sys/libnftnl.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | -------------------------------------------------------------------------------- /nftnl-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amagicom AB. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Low level FFI bindings to [`libnftnl`], a userspace library providing a low-level netlink 10 | //! programming interface (API) to the in-kernel nf_tables subsystem. 11 | //! 12 | //! See [`nftnl`] for a higher level safe abstraction. 13 | //! 14 | //! # Linking to libmnl and libnftnl 15 | //! 16 | //! By default this crate uses pkg-config to find and link to its C dependencies, [`libmnl`] and 17 | //! [`libnftnl`]. To manually configure where to look for these libraries, set the environment 18 | //! variables `LIBMNL_LIB_DIR` and `LIBNFTNL_LIB_DIR` to point to the directories where `libmnl.so` 19 | //! (or `libmnl.a`) and `libnftnl.so` (or `libnftnl.a`) reside. 20 | //! 21 | //! # Selecting version of `libnftnl` 22 | //! 23 | //! This crate has bindings for most versions of [`libnftnl`]. All bindings are generated by 24 | //! [`bindgen`] via the `generate_bindings.sh` script in this repository. 25 | //! 26 | //! Only one version of `libnftnl` can be exposed via this crate. By default the crate exports the 27 | //! bindings for the oldest supported version (`libnftnl-1.0.6`). To get newer versions activate the 28 | //! corresponding features. See `Cargo.toml` for available features/versions. 29 | //! 30 | //! So for example, to get bindings to `libnftnl-1.0.9` depend on this crate like this: 31 | //! ```toml 32 | //! [dependencies] 33 | //! nftnl-sys = { version = "0.1", features = ["nftnl-1-0-9"] } 34 | //! ``` 35 | //! 36 | //! [`libnftnl`]: https://netfilter.org/projects/libnftnl/ 37 | //! [`libmnl`]: https://netfilter.org/projects/libmnl/ 38 | //! [`nftnl`]: https://crates.io/crates/nftnl 39 | //! [`bindgen`]: https://crates.io/crates/bindgen 40 | 41 | #![no_std] 42 | #![cfg(target_os = "linux")] 43 | #![allow(non_camel_case_types)] 44 | 45 | pub use libc; 46 | 47 | cfg_if::cfg_if! { 48 | if #[cfg(feature = "nftnl-1-1-2")] { 49 | mod nftnl_1_1_2; 50 | pub use self::nftnl_1_1_2::*; 51 | } else if #[cfg(feature = "nftnl-1-1-1")] { 52 | mod nftnl_1_1_1; 53 | pub use self::nftnl_1_1_1::*; 54 | } else if #[cfg(feature = "nftnl-1-1-0")] { 55 | mod nftnl_1_1_0; 56 | pub use self::nftnl_1_1_0::*; 57 | } else if #[cfg(feature = "nftnl-1-0-9")] { 58 | mod nftnl_1_0_9; 59 | pub use self::nftnl_1_0_9::*; 60 | } else if #[cfg(feature = "nftnl-1-0-8")] { 61 | mod nftnl_1_0_8; 62 | pub use self::nftnl_1_0_8::*; 63 | } else if #[cfg(feature = "nftnl-1-0-7")] { 64 | mod nftnl_1_0_7; 65 | pub use self::nftnl_1_0_7::*; 66 | } else { 67 | mod nftnl_1_0_6; 68 | pub use self::nftnl_1_0_6::*; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /nftnl-sys/src/nftnl_1_0_6.rs: -------------------------------------------------------------------------------- 1 | // automatically generated by rust-bindgen 0.39.0 2 | 3 | use core::option::Option; 4 | use libc::{c_char, c_int, c_void, iovec, nlmsghdr, FILE}; 5 | 6 | #[repr(C)] 7 | pub struct nftnl_batch(c_void); 8 | 9 | extern "C" { 10 | pub fn nftnl_batch_alloc(pg_size: u32, pg_overrun_size: u32) -> *mut nftnl_batch; 11 | 12 | pub fn nftnl_batch_update(batch: *mut nftnl_batch) -> c_int; 13 | 14 | pub fn nftnl_batch_free(batch: *mut nftnl_batch); 15 | 16 | pub fn nftnl_batch_buffer(batch: *mut nftnl_batch) -> *mut c_void; 17 | 18 | pub fn nftnl_batch_buffer_len(batch: *mut nftnl_batch) -> u32; 19 | 20 | pub fn nftnl_batch_iovec_len(batch: *mut nftnl_batch) -> c_int; 21 | 22 | pub fn nftnl_batch_iovec(batch: *mut nftnl_batch, iov: *mut iovec, iovlen: u32); 23 | } 24 | pub const NFTNL_PARSE_EBADINPUT: u32 = 0; 25 | pub const NFTNL_PARSE_EMISSINGNODE: u32 = 1; 26 | pub const NFTNL_PARSE_EBADTYPE: u32 = 2; 27 | pub const NFTNL_PARSE_EOPNOTSUPP: u32 = 3; 28 | 29 | pub const NFTNL_OUTPUT_DEFAULT: nftnl_output_type = 0; 30 | pub const NFTNL_OUTPUT_XML: nftnl_output_type = 1; 31 | pub const NFTNL_OUTPUT_JSON: nftnl_output_type = 2; 32 | pub type nftnl_output_type = u32; 33 | pub const NFTNL_OF_EVENT_NEW: nftnl_output_flags = 1; 34 | pub const NFTNL_OF_EVENT_DEL: nftnl_output_flags = 2; 35 | pub const NFTNL_OF_EVENT_ANY: nftnl_output_flags = 3; 36 | pub type nftnl_output_flags = u32; 37 | pub const NFTNL_CMD_UNSPEC: nftnl_cmd_type = 0; 38 | pub const NFTNL_CMD_ADD: nftnl_cmd_type = 1; 39 | pub const NFTNL_CMD_INSERT: nftnl_cmd_type = 2; 40 | pub const NFTNL_CMD_DELETE: nftnl_cmd_type = 3; 41 | pub const NFTNL_CMD_REPLACE: nftnl_cmd_type = 4; 42 | pub const NFTNL_CMD_FLUSH: nftnl_cmd_type = 5; 43 | pub const NFTNL_CMD_MAX: nftnl_cmd_type = 6; 44 | pub type nftnl_cmd_type = u32; 45 | pub const NFTNL_PARSE_NONE: nftnl_parse_type = 0; 46 | pub const NFTNL_PARSE_XML: nftnl_parse_type = 1; 47 | pub const NFTNL_PARSE_JSON: nftnl_parse_type = 2; 48 | pub const NFTNL_PARSE_MAX: nftnl_parse_type = 3; 49 | pub type nftnl_parse_type = u32; 50 | #[repr(C)] 51 | pub struct nftnl_parse_err(c_void); 52 | 53 | extern "C" { 54 | pub fn nftnl_nlmsg_build_hdr( 55 | buf: *mut c_char, 56 | cmd: u16, 57 | family: u16, 58 | type_: u16, 59 | seq: u32, 60 | ) -> *mut nlmsghdr; 61 | 62 | pub fn nftnl_parse_err_alloc() -> *mut nftnl_parse_err; 63 | 64 | pub fn nftnl_parse_err_free(arg1: *mut nftnl_parse_err); 65 | 66 | pub fn nftnl_parse_perror(str: *const c_char, err: *mut nftnl_parse_err) -> c_int; 67 | 68 | pub fn nftnl_batch_is_supported() -> c_int; 69 | 70 | pub fn nftnl_batch_begin(buf: *mut c_char, seq: u32); 71 | 72 | pub fn nftnl_batch_end(buf: *mut c_char, seq: u32); 73 | } 74 | #[repr(C)] 75 | pub struct nftnl_chain(c_void); 76 | 77 | extern "C" { 78 | pub fn nftnl_chain_alloc() -> *mut nftnl_chain; 79 | 80 | pub fn nftnl_chain_free(arg1: *const nftnl_chain); 81 | } 82 | pub const NFTNL_CHAIN_NAME: nftnl_chain_attr = 0; 83 | pub const NFTNL_CHAIN_FAMILY: nftnl_chain_attr = 1; 84 | pub const NFTNL_CHAIN_TABLE: nftnl_chain_attr = 2; 85 | pub const NFTNL_CHAIN_HOOKNUM: nftnl_chain_attr = 3; 86 | pub const NFTNL_CHAIN_PRIO: nftnl_chain_attr = 4; 87 | pub const NFTNL_CHAIN_POLICY: nftnl_chain_attr = 5; 88 | pub const NFTNL_CHAIN_USE: nftnl_chain_attr = 6; 89 | pub const NFTNL_CHAIN_BYTES: nftnl_chain_attr = 7; 90 | pub const NFTNL_CHAIN_PACKETS: nftnl_chain_attr = 8; 91 | pub const NFTNL_CHAIN_HANDLE: nftnl_chain_attr = 9; 92 | pub const NFTNL_CHAIN_TYPE: nftnl_chain_attr = 10; 93 | pub const NFTNL_CHAIN_DEV: nftnl_chain_attr = 11; 94 | pub const __NFTNL_CHAIN_MAX: nftnl_chain_attr = 12; 95 | pub type nftnl_chain_attr = u32; 96 | extern "C" { 97 | pub fn nftnl_chain_is_set(c: *const nftnl_chain, attr: u16) -> bool; 98 | 99 | pub fn nftnl_chain_unset(c: *mut nftnl_chain, attr: u16); 100 | 101 | pub fn nftnl_chain_set(t: *mut nftnl_chain, attr: u16, data: *const c_void); 102 | 103 | pub fn nftnl_chain_set_data(t: *mut nftnl_chain, attr: u16, data: *const c_void, data_len: u32); 104 | 105 | pub fn nftnl_chain_set_u8(t: *mut nftnl_chain, attr: u16, data: u8); 106 | 107 | pub fn nftnl_chain_set_u32(t: *mut nftnl_chain, attr: u16, data: u32); 108 | 109 | pub fn nftnl_chain_set_s32(t: *mut nftnl_chain, attr: u16, data: i32); 110 | 111 | pub fn nftnl_chain_set_u64(t: *mut nftnl_chain, attr: u16, data: u64); 112 | 113 | pub fn nftnl_chain_set_str(t: *mut nftnl_chain, attr: u16, str: *const c_char); 114 | 115 | pub fn nftnl_chain_get(c: *const nftnl_chain, attr: u16) -> *const c_void; 116 | 117 | pub fn nftnl_chain_get_data( 118 | c: *const nftnl_chain, 119 | attr: u16, 120 | data_len: *mut u32, 121 | ) -> *const c_void; 122 | 123 | pub fn nftnl_chain_get_str(c: *const nftnl_chain, attr: u16) -> *const c_char; 124 | 125 | pub fn nftnl_chain_get_u8(c: *const nftnl_chain, attr: u16) -> u8; 126 | 127 | pub fn nftnl_chain_get_u32(c: *const nftnl_chain, attr: u16) -> u32; 128 | 129 | pub fn nftnl_chain_get_s32(c: *const nftnl_chain, attr: u16) -> i32; 130 | 131 | pub fn nftnl_chain_get_u64(c: *const nftnl_chain, attr: u16) -> u64; 132 | 133 | pub fn nftnl_chain_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *const nftnl_chain); 134 | 135 | pub fn nftnl_chain_parse( 136 | c: *mut nftnl_chain, 137 | type_: nftnl_parse_type, 138 | data: *const c_char, 139 | err: *mut nftnl_parse_err, 140 | ) -> c_int; 141 | 142 | pub fn nftnl_chain_parse_file( 143 | c: *mut nftnl_chain, 144 | type_: nftnl_parse_type, 145 | fp: *mut FILE, 146 | err: *mut nftnl_parse_err, 147 | ) -> c_int; 148 | 149 | pub fn nftnl_chain_snprintf( 150 | buf: *mut c_char, 151 | size: usize, 152 | t: *const nftnl_chain, 153 | type_: u32, 154 | flags: u32, 155 | ) -> c_int; 156 | 157 | pub fn nftnl_chain_fprintf( 158 | fp: *mut FILE, 159 | c: *const nftnl_chain, 160 | type_: u32, 161 | flags: u32, 162 | ) -> c_int; 163 | 164 | pub fn nftnl_chain_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_chain) -> c_int; 165 | } 166 | #[repr(C)] 167 | pub struct nftnl_chain_list(c_void); 168 | 169 | extern "C" { 170 | pub fn nftnl_chain_list_alloc() -> *mut nftnl_chain_list; 171 | 172 | pub fn nftnl_chain_list_free(list: *mut nftnl_chain_list); 173 | 174 | pub fn nftnl_chain_list_is_empty(list: *const nftnl_chain_list) -> c_int; 175 | 176 | pub fn nftnl_chain_list_foreach( 177 | chain_list: *mut nftnl_chain_list, 178 | cb: Option c_int>, 179 | data: *mut c_void, 180 | ) -> c_int; 181 | 182 | pub fn nftnl_chain_list_add(r: *mut nftnl_chain, list: *mut nftnl_chain_list); 183 | 184 | pub fn nftnl_chain_list_add_tail(r: *mut nftnl_chain, list: *mut nftnl_chain_list); 185 | 186 | pub fn nftnl_chain_list_del(c: *mut nftnl_chain); 187 | } 188 | #[repr(C)] 189 | pub struct nftnl_chain_list_iter(c_void); 190 | 191 | extern "C" { 192 | pub fn nftnl_chain_list_iter_create(l: *mut nftnl_chain_list) -> *mut nftnl_chain_list_iter; 193 | 194 | pub fn nftnl_chain_list_iter_next(iter: *mut nftnl_chain_list_iter) -> *mut nftnl_chain; 195 | 196 | pub fn nftnl_chain_list_iter_destroy(iter: *mut nftnl_chain_list_iter); 197 | } 198 | #[repr(C)] 199 | pub struct nftnl_expr(c_void); 200 | 201 | pub const NFTNL_EXPR_NAME: u32 = 0; 202 | pub const NFTNL_EXPR_BASE: u32 = 1; 203 | 204 | extern "C" { 205 | pub fn nftnl_expr_alloc(name: *const c_char) -> *mut nftnl_expr; 206 | 207 | pub fn nftnl_expr_free(expr: *const nftnl_expr); 208 | 209 | pub fn nftnl_expr_is_set(expr: *const nftnl_expr, type_: u16) -> bool; 210 | 211 | pub fn nftnl_expr_set(expr: *mut nftnl_expr, type_: u16, data: *const c_void, data_len: u32); 212 | 213 | pub fn nftnl_expr_set_u8(expr: *mut nftnl_expr, type_: u16, data: u8); 214 | 215 | pub fn nftnl_expr_set_u16(expr: *mut nftnl_expr, type_: u16, data: u16); 216 | 217 | pub fn nftnl_expr_set_u32(expr: *mut nftnl_expr, type_: u16, data: u32); 218 | 219 | pub fn nftnl_expr_set_u64(expr: *mut nftnl_expr, type_: u16, data: u64); 220 | 221 | pub fn nftnl_expr_set_str(expr: *mut nftnl_expr, type_: u16, str: *const c_char); 222 | 223 | pub fn nftnl_expr_get(expr: *const nftnl_expr, type_: u16, data_len: *mut u32) 224 | -> *const c_void; 225 | 226 | pub fn nftnl_expr_get_u8(expr: *const nftnl_expr, type_: u16) -> u8; 227 | 228 | pub fn nftnl_expr_get_u16(expr: *const nftnl_expr, type_: u16) -> u16; 229 | 230 | pub fn nftnl_expr_get_u32(expr: *const nftnl_expr, type_: u16) -> u32; 231 | 232 | pub fn nftnl_expr_get_u64(expr: *const nftnl_expr, type_: u16) -> u64; 233 | 234 | pub fn nftnl_expr_get_str(expr: *const nftnl_expr, type_: u16) -> *const c_char; 235 | 236 | pub fn nftnl_expr_snprintf( 237 | buf: *mut c_char, 238 | buflen: usize, 239 | expr: *const nftnl_expr, 240 | type_: u32, 241 | flags: u32, 242 | ) -> c_int; 243 | } 244 | pub const NFTNL_EXPR_PAYLOAD_DREG: u32 = 1; 245 | pub const NFTNL_EXPR_PAYLOAD_BASE: u32 = 2; 246 | pub const NFTNL_EXPR_PAYLOAD_OFFSET: u32 = 3; 247 | pub const NFTNL_EXPR_PAYLOAD_LEN: u32 = 4; 248 | pub const NFTNL_EXPR_PAYLOAD_SREG: u32 = 5; 249 | pub const NFTNL_EXPR_PAYLOAD_CSUM_TYPE: u32 = 6; 250 | pub const NFTNL_EXPR_PAYLOAD_CSUM_OFFSET: u32 = 7; 251 | 252 | pub const NFTNL_EXPR_META_KEY: u32 = 1; 253 | pub const NFTNL_EXPR_META_DREG: u32 = 2; 254 | pub const NFTNL_EXPR_META_SREG: u32 = 3; 255 | 256 | pub const NFTNL_EXPR_CMP_SREG: u32 = 1; 257 | pub const NFTNL_EXPR_CMP_OP: u32 = 2; 258 | pub const NFTNL_EXPR_CMP_DATA: u32 = 3; 259 | 260 | pub const NFTNL_EXPR_IMM_DREG: u32 = 1; 261 | pub const NFTNL_EXPR_IMM_DATA: u32 = 2; 262 | pub const NFTNL_EXPR_IMM_VERDICT: u32 = 3; 263 | pub const NFTNL_EXPR_IMM_CHAIN: u32 = 4; 264 | 265 | pub const NFTNL_EXPR_CTR_PACKETS: u32 = 1; 266 | pub const NFTNL_EXPR_CTR_BYTES: u32 = 2; 267 | 268 | pub const NFTNL_EXPR_BITWISE_SREG: u32 = 1; 269 | pub const NFTNL_EXPR_BITWISE_DREG: u32 = 2; 270 | pub const NFTNL_EXPR_BITWISE_LEN: u32 = 3; 271 | pub const NFTNL_EXPR_BITWISE_MASK: u32 = 4; 272 | pub const NFTNL_EXPR_BITWISE_XOR: u32 = 5; 273 | 274 | pub const NFTNL_EXPR_TG_NAME: u32 = 1; 275 | pub const NFTNL_EXPR_TG_REV: u32 = 2; 276 | pub const NFTNL_EXPR_TG_INFO: u32 = 3; 277 | 278 | pub const NFTNL_EXPR_MT_NAME: u32 = 1; 279 | pub const NFTNL_EXPR_MT_REV: u32 = 2; 280 | pub const NFTNL_EXPR_MT_INFO: u32 = 3; 281 | 282 | pub const NFTNL_EXPR_NAT_TYPE: u32 = 1; 283 | pub const NFTNL_EXPR_NAT_FAMILY: u32 = 2; 284 | pub const NFTNL_EXPR_NAT_REG_ADDR_MIN: u32 = 3; 285 | pub const NFTNL_EXPR_NAT_REG_ADDR_MAX: u32 = 4; 286 | pub const NFTNL_EXPR_NAT_REG_PROTO_MIN: u32 = 5; 287 | pub const NFTNL_EXPR_NAT_REG_PROTO_MAX: u32 = 6; 288 | pub const NFTNL_EXPR_NAT_FLAGS: u32 = 7; 289 | 290 | pub const NFTNL_EXPR_LOOKUP_SREG: u32 = 1; 291 | pub const NFTNL_EXPR_LOOKUP_DREG: u32 = 2; 292 | pub const NFTNL_EXPR_LOOKUP_SET: u32 = 3; 293 | pub const NFTNL_EXPR_LOOKUP_SET_ID: u32 = 4; 294 | 295 | pub const NFTNL_EXPR_DYNSET_SREG_KEY: u32 = 1; 296 | pub const NFTNL_EXPR_DYNSET_SREG_DATA: u32 = 2; 297 | pub const NFTNL_EXPR_DYNSET_OP: u32 = 3; 298 | pub const NFTNL_EXPR_DYNSET_TIMEOUT: u32 = 4; 299 | pub const NFTNL_EXPR_DYNSET_SET_NAME: u32 = 5; 300 | pub const NFTNL_EXPR_DYNSET_SET_ID: u32 = 6; 301 | pub const NFTNL_EXPR_DYNSET_EXPR: u32 = 7; 302 | 303 | pub const NFTNL_EXPR_LOG_PREFIX: u32 = 1; 304 | pub const NFTNL_EXPR_LOG_GROUP: u32 = 2; 305 | pub const NFTNL_EXPR_LOG_SNAPLEN: u32 = 3; 306 | pub const NFTNL_EXPR_LOG_QTHRESHOLD: u32 = 4; 307 | pub const NFTNL_EXPR_LOG_LEVEL: u32 = 5; 308 | pub const NFTNL_EXPR_LOG_FLAGS: u32 = 6; 309 | 310 | pub const NFTNL_EXPR_EXTHDR_DREG: u32 = 1; 311 | pub const NFTNL_EXPR_EXTHDR_TYPE: u32 = 2; 312 | pub const NFTNL_EXPR_EXTHDR_OFFSET: u32 = 3; 313 | pub const NFTNL_EXPR_EXTHDR_LEN: u32 = 4; 314 | 315 | pub const NFTNL_EXPR_CT_DREG: u32 = 1; 316 | pub const NFTNL_EXPR_CT_KEY: u32 = 2; 317 | pub const NFTNL_EXPR_CT_DIR: u32 = 3; 318 | pub const NFTNL_EXPR_CT_SREG: u32 = 4; 319 | 320 | pub const NFTNL_EXPR_BYTEORDER_DREG: u32 = 1; 321 | pub const NFTNL_EXPR_BYTEORDER_SREG: u32 = 2; 322 | pub const NFTNL_EXPR_BYTEORDER_OP: u32 = 3; 323 | pub const NFTNL_EXPR_BYTEORDER_LEN: u32 = 4; 324 | pub const NFTNL_EXPR_BYTEORDER_SIZE: u32 = 5; 325 | 326 | pub const NFTNL_EXPR_LIMIT_RATE: u32 = 1; 327 | pub const NFTNL_EXPR_LIMIT_UNIT: u32 = 2; 328 | pub const NFTNL_EXPR_LIMIT_BURST: u32 = 3; 329 | pub const NFTNL_EXPR_LIMIT_TYPE: u32 = 4; 330 | pub const NFTNL_EXPR_LIMIT_FLAGS: u32 = 5; 331 | 332 | pub const NFTNL_EXPR_REJECT_TYPE: u32 = 1; 333 | pub const NFTNL_EXPR_REJECT_CODE: u32 = 2; 334 | 335 | pub const NFTNL_EXPR_QUEUE_NUM: u32 = 1; 336 | pub const NFTNL_EXPR_QUEUE_TOTAL: u32 = 2; 337 | pub const NFTNL_EXPR_QUEUE_FLAGS: u32 = 3; 338 | 339 | pub const NFTNL_EXPR_MASQ_FLAGS: u32 = 1; 340 | pub const NFTNL_EXPR_MASQ_REG_PROTO_MIN: u32 = 2; 341 | pub const NFTNL_EXPR_MASQ_REG_PROTO_MAX: u32 = 3; 342 | 343 | pub const NFTNL_EXPR_REDIR_REG_PROTO_MIN: u32 = 1; 344 | pub const NFTNL_EXPR_REDIR_REG_PROTO_MAX: u32 = 2; 345 | pub const NFTNL_EXPR_REDIR_FLAGS: u32 = 3; 346 | 347 | pub const NFTNL_EXPR_DUP_SREG_ADDR: u32 = 1; 348 | pub const NFTNL_EXPR_DUP_SREG_DEV: u32 = 2; 349 | 350 | pub const NFTNL_EXPR_FWD_SREG_DEV: u32 = 1; 351 | 352 | #[repr(C)] 353 | pub struct nftnl_gen(c_void); 354 | 355 | extern "C" { 356 | pub fn nftnl_gen_alloc() -> *mut nftnl_gen; 357 | 358 | pub fn nftnl_gen_free(arg1: *const nftnl_gen); 359 | } 360 | pub const NFTNL_GEN_ID: u32 = 0; 361 | pub const __NFTNL_GEN_MAX: u32 = 1; 362 | 363 | extern "C" { 364 | pub fn nftnl_gen_is_set(gen: *const nftnl_gen, attr: u16) -> bool; 365 | 366 | pub fn nftnl_gen_unset(gen: *mut nftnl_gen, attr: u16); 367 | 368 | pub fn nftnl_gen_set(gen: *mut nftnl_gen, attr: u16, data: *const c_void); 369 | 370 | pub fn nftnl_gen_set_data(gen: *mut nftnl_gen, attr: u16, data: *const c_void, data_len: u32); 371 | 372 | pub fn nftnl_gen_get(gen: *const nftnl_gen, attr: u16) -> *const c_void; 373 | 374 | pub fn nftnl_gen_get_data( 375 | gen: *const nftnl_gen, 376 | attr: u16, 377 | data_len: *mut u32, 378 | ) -> *const c_void; 379 | 380 | pub fn nftnl_gen_set_u32(gen: *mut nftnl_gen, attr: u16, data: u32); 381 | 382 | pub fn nftnl_gen_get_u32(gen: *const nftnl_gen, attr: u16) -> u32; 383 | 384 | pub fn nftnl_gen_nlmsg_parse(nlh: *const nlmsghdr, gen: *mut nftnl_gen) -> c_int; 385 | 386 | pub fn nftnl_gen_snprintf( 387 | buf: *mut c_char, 388 | size: usize, 389 | gen: *const nftnl_gen, 390 | type_: u32, 391 | flags: u32, 392 | ) -> c_int; 393 | 394 | pub fn nftnl_gen_fprintf(fp: *mut FILE, gen: *const nftnl_gen, type_: u32, flags: u32) 395 | -> c_int; 396 | } 397 | #[repr(C)] 398 | pub struct nftnl_rule(c_void); 399 | 400 | extern "C" { 401 | pub fn nftnl_rule_alloc() -> *mut nftnl_rule; 402 | 403 | pub fn nftnl_rule_free(arg1: *const nftnl_rule); 404 | } 405 | pub const NFTNL_RULE_FAMILY: nftnl_rule_attr = 0; 406 | pub const NFTNL_RULE_TABLE: nftnl_rule_attr = 1; 407 | pub const NFTNL_RULE_CHAIN: nftnl_rule_attr = 2; 408 | pub const NFTNL_RULE_HANDLE: nftnl_rule_attr = 3; 409 | pub const NFTNL_RULE_COMPAT_PROTO: nftnl_rule_attr = 4; 410 | pub const NFTNL_RULE_COMPAT_FLAGS: nftnl_rule_attr = 5; 411 | pub const NFTNL_RULE_POSITION: nftnl_rule_attr = 6; 412 | pub const NFTNL_RULE_USERDATA: nftnl_rule_attr = 7; 413 | pub const __NFTNL_RULE_MAX: nftnl_rule_attr = 8; 414 | pub type nftnl_rule_attr = u32; 415 | extern "C" { 416 | pub fn nftnl_rule_unset(r: *mut nftnl_rule, attr: u16); 417 | 418 | pub fn nftnl_rule_is_set(r: *const nftnl_rule, attr: u16) -> bool; 419 | 420 | pub fn nftnl_rule_set(r: *mut nftnl_rule, attr: u16, data: *const c_void); 421 | 422 | pub fn nftnl_rule_set_data(r: *mut nftnl_rule, attr: u16, data: *const c_void, data_len: u32); 423 | 424 | pub fn nftnl_rule_set_u32(r: *mut nftnl_rule, attr: u16, val: u32); 425 | 426 | pub fn nftnl_rule_set_u64(r: *mut nftnl_rule, attr: u16, val: u64); 427 | 428 | pub fn nftnl_rule_set_str(r: *mut nftnl_rule, attr: u16, str: *const c_char); 429 | 430 | pub fn nftnl_rule_get(r: *const nftnl_rule, attr: u16) -> *const c_void; 431 | 432 | pub fn nftnl_rule_get_data( 433 | r: *const nftnl_rule, 434 | attr: u16, 435 | data_len: *mut u32, 436 | ) -> *const c_void; 437 | 438 | pub fn nftnl_rule_get_str(r: *const nftnl_rule, attr: u16) -> *const c_char; 439 | 440 | pub fn nftnl_rule_get_u8(r: *const nftnl_rule, attr: u16) -> u8; 441 | 442 | pub fn nftnl_rule_get_u32(r: *const nftnl_rule, attr: u16) -> u32; 443 | 444 | pub fn nftnl_rule_get_u64(r: *const nftnl_rule, attr: u16) -> u64; 445 | 446 | pub fn nftnl_rule_add_expr(r: *mut nftnl_rule, expr: *mut nftnl_expr); 447 | 448 | pub fn nftnl_rule_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *mut nftnl_rule); 449 | 450 | pub fn nftnl_rule_parse( 451 | r: *mut nftnl_rule, 452 | type_: nftnl_parse_type, 453 | data: *const c_char, 454 | err: *mut nftnl_parse_err, 455 | ) -> c_int; 456 | 457 | pub fn nftnl_rule_parse_file( 458 | r: *mut nftnl_rule, 459 | type_: nftnl_parse_type, 460 | fp: *mut FILE, 461 | err: *mut nftnl_parse_err, 462 | ) -> c_int; 463 | 464 | pub fn nftnl_rule_snprintf( 465 | buf: *mut c_char, 466 | size: usize, 467 | t: *const nftnl_rule, 468 | type_: u32, 469 | flags: u32, 470 | ) -> c_int; 471 | 472 | pub fn nftnl_rule_fprintf(fp: *mut FILE, r: *const nftnl_rule, type_: u32, flags: u32) 473 | -> c_int; 474 | 475 | pub fn nftnl_rule_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_rule) -> c_int; 476 | 477 | pub fn nftnl_expr_foreach( 478 | r: *mut nftnl_rule, 479 | cb: Option c_int>, 480 | data: *mut c_void, 481 | ) -> c_int; 482 | } 483 | #[repr(C)] 484 | pub struct nftnl_expr_iter(c_void); 485 | 486 | extern "C" { 487 | pub fn nftnl_expr_iter_create(r: *mut nftnl_rule) -> *mut nftnl_expr_iter; 488 | 489 | pub fn nftnl_expr_iter_next(iter: *mut nftnl_expr_iter) -> *mut nftnl_expr; 490 | 491 | pub fn nftnl_expr_iter_destroy(iter: *mut nftnl_expr_iter); 492 | } 493 | #[repr(C)] 494 | pub struct nftnl_rule_list(c_void); 495 | 496 | extern "C" { 497 | pub fn nftnl_rule_list_alloc() -> *mut nftnl_rule_list; 498 | 499 | pub fn nftnl_rule_list_free(list: *mut nftnl_rule_list); 500 | 501 | pub fn nftnl_rule_list_is_empty(list: *const nftnl_rule_list) -> c_int; 502 | 503 | pub fn nftnl_rule_list_add(r: *mut nftnl_rule, list: *mut nftnl_rule_list); 504 | 505 | pub fn nftnl_rule_list_add_tail(r: *mut nftnl_rule, list: *mut nftnl_rule_list); 506 | 507 | pub fn nftnl_rule_list_del(r: *mut nftnl_rule); 508 | 509 | pub fn nftnl_rule_list_foreach( 510 | rule_list: *mut nftnl_rule_list, 511 | cb: Option c_int>, 512 | data: *mut c_void, 513 | ) -> c_int; 514 | } 515 | #[repr(C)] 516 | pub struct nftnl_rule_list_iter(c_void); 517 | 518 | extern "C" { 519 | pub fn nftnl_rule_list_iter_create(l: *mut nftnl_rule_list) -> *mut nftnl_rule_list_iter; 520 | 521 | pub fn nftnl_rule_list_iter_cur(iter: *mut nftnl_rule_list_iter) -> *mut nftnl_rule; 522 | 523 | pub fn nftnl_rule_list_iter_next(iter: *mut nftnl_rule_list_iter) -> *mut nftnl_rule; 524 | 525 | pub fn nftnl_rule_list_iter_destroy(iter: *const nftnl_rule_list_iter); 526 | } 527 | #[repr(C)] 528 | pub struct nftnl_ruleset(c_void); 529 | 530 | extern "C" { 531 | pub fn nftnl_ruleset_alloc() -> *mut nftnl_ruleset; 532 | 533 | pub fn nftnl_ruleset_free(r: *const nftnl_ruleset); 534 | } 535 | pub const NFTNL_RULESET_TABLELIST: u32 = 0; 536 | pub const NFTNL_RULESET_CHAINLIST: u32 = 1; 537 | pub const NFTNL_RULESET_SETLIST: u32 = 2; 538 | pub const NFTNL_RULESET_RULELIST: u32 = 3; 539 | 540 | pub const NFTNL_RULESET_UNSPEC: nftnl_ruleset_type = 0; 541 | pub const NFTNL_RULESET_RULESET: nftnl_ruleset_type = 1; 542 | pub const NFTNL_RULESET_TABLE: nftnl_ruleset_type = 2; 543 | pub const NFTNL_RULESET_CHAIN: nftnl_ruleset_type = 3; 544 | pub const NFTNL_RULESET_RULE: nftnl_ruleset_type = 4; 545 | pub const NFTNL_RULESET_SET: nftnl_ruleset_type = 5; 546 | pub const NFTNL_RULESET_SET_ELEMS: nftnl_ruleset_type = 6; 547 | pub type nftnl_ruleset_type = u32; 548 | extern "C" { 549 | pub fn nftnl_ruleset_is_set(r: *const nftnl_ruleset, attr: u16) -> bool; 550 | 551 | pub fn nftnl_ruleset_unset(r: *mut nftnl_ruleset, attr: u16); 552 | 553 | pub fn nftnl_ruleset_set(r: *mut nftnl_ruleset, attr: u16, data: *mut c_void); 554 | 555 | pub fn nftnl_ruleset_get(r: *const nftnl_ruleset, attr: u16) -> *mut c_void; 556 | } 557 | pub const NFTNL_RULESET_CTX_CMD: u32 = 0; 558 | pub const NFTNL_RULESET_CTX_TYPE: u32 = 1; 559 | pub const NFTNL_RULESET_CTX_TABLE: u32 = 2; 560 | pub const NFTNL_RULESET_CTX_CHAIN: u32 = 3; 561 | pub const NFTNL_RULESET_CTX_RULE: u32 = 4; 562 | pub const NFTNL_RULESET_CTX_SET: u32 = 5; 563 | pub const NFTNL_RULESET_CTX_DATA: u32 = 6; 564 | 565 | #[repr(C)] 566 | pub struct nftnl_parse_ctx(c_void); 567 | 568 | extern "C" { 569 | pub fn nftnl_ruleset_ctx_free(ctx: *const nftnl_parse_ctx); 570 | 571 | pub fn nftnl_ruleset_ctx_is_set(ctx: *const nftnl_parse_ctx, attr: u16) -> bool; 572 | 573 | pub fn nftnl_ruleset_ctx_get(ctx: *const nftnl_parse_ctx, attr: u16) -> *mut c_void; 574 | 575 | pub fn nftnl_ruleset_ctx_get_u32(ctx: *const nftnl_parse_ctx, attr: u16) -> u32; 576 | 577 | pub fn nftnl_ruleset_parse_file_cb( 578 | type_: nftnl_parse_type, 579 | fp: *mut FILE, 580 | err: *mut nftnl_parse_err, 581 | data: *mut c_void, 582 | cb: Option c_int>, 583 | ) -> c_int; 584 | 585 | pub fn nftnl_ruleset_parse_buffer_cb( 586 | type_: nftnl_parse_type, 587 | buffer: *const c_char, 588 | err: *mut nftnl_parse_err, 589 | data: *mut c_void, 590 | cb: Option c_int>, 591 | ) -> c_int; 592 | 593 | pub fn nftnl_ruleset_parse( 594 | rs: *mut nftnl_ruleset, 595 | type_: nftnl_parse_type, 596 | data: *const c_char, 597 | err: *mut nftnl_parse_err, 598 | ) -> c_int; 599 | 600 | pub fn nftnl_ruleset_parse_file( 601 | rs: *mut nftnl_ruleset, 602 | type_: nftnl_parse_type, 603 | fp: *mut FILE, 604 | err: *mut nftnl_parse_err, 605 | ) -> c_int; 606 | 607 | pub fn nftnl_ruleset_snprintf( 608 | buf: *mut c_char, 609 | size: usize, 610 | rs: *const nftnl_ruleset, 611 | type_: u32, 612 | flags: u32, 613 | ) -> c_int; 614 | 615 | pub fn nftnl_ruleset_fprintf( 616 | fp: *mut FILE, 617 | rs: *const nftnl_ruleset, 618 | type_: u32, 619 | flags: u32, 620 | ) -> c_int; 621 | } 622 | pub const NFTNL_SET_TABLE: nftnl_set_attr = 0; 623 | pub const NFTNL_SET_NAME: nftnl_set_attr = 1; 624 | pub const NFTNL_SET_FLAGS: nftnl_set_attr = 2; 625 | pub const NFTNL_SET_KEY_TYPE: nftnl_set_attr = 3; 626 | pub const NFTNL_SET_KEY_LEN: nftnl_set_attr = 4; 627 | pub const NFTNL_SET_DATA_TYPE: nftnl_set_attr = 5; 628 | pub const NFTNL_SET_DATA_LEN: nftnl_set_attr = 6; 629 | pub const NFTNL_SET_FAMILY: nftnl_set_attr = 7; 630 | pub const NFTNL_SET_ID: nftnl_set_attr = 8; 631 | pub const NFTNL_SET_POLICY: nftnl_set_attr = 9; 632 | pub const NFTNL_SET_DESC_SIZE: nftnl_set_attr = 10; 633 | pub const NFTNL_SET_TIMEOUT: nftnl_set_attr = 11; 634 | pub const NFTNL_SET_GC_INTERVAL: nftnl_set_attr = 12; 635 | pub const __NFTNL_SET_MAX: nftnl_set_attr = 13; 636 | pub type nftnl_set_attr = u32; 637 | #[repr(C)] 638 | pub struct nftnl_set(c_void); 639 | 640 | extern "C" { 641 | pub fn nftnl_set_alloc() -> *mut nftnl_set; 642 | 643 | pub fn nftnl_set_free(s: *const nftnl_set); 644 | 645 | pub fn nftnl_set_clone(set: *const nftnl_set) -> *mut nftnl_set; 646 | 647 | pub fn nftnl_set_is_set(s: *const nftnl_set, attr: u16) -> bool; 648 | 649 | pub fn nftnl_set_unset(s: *mut nftnl_set, attr: u16); 650 | 651 | pub fn nftnl_set_set(s: *mut nftnl_set, attr: u16, data: *const c_void); 652 | 653 | pub fn nftnl_set_set_data(s: *mut nftnl_set, attr: u16, data: *const c_void, data_len: u32); 654 | 655 | pub fn nftnl_set_set_u32(s: *mut nftnl_set, attr: u16, val: u32); 656 | 657 | pub fn nftnl_set_set_u64(s: *mut nftnl_set, attr: u16, val: u64); 658 | 659 | pub fn nftnl_set_set_str(s: *mut nftnl_set, attr: u16, str: *const c_char); 660 | 661 | pub fn nftnl_set_get(s: *const nftnl_set, attr: u16) -> *const c_void; 662 | 663 | pub fn nftnl_set_get_data(s: *const nftnl_set, attr: u16, data_len: *mut u32) -> *const c_void; 664 | 665 | pub fn nftnl_set_get_str(s: *const nftnl_set, attr: u16) -> *const c_char; 666 | 667 | pub fn nftnl_set_get_u32(s: *const nftnl_set, attr: u16) -> u32; 668 | 669 | pub fn nftnl_set_get_u64(s: *const nftnl_set, attr: u16) -> u64; 670 | 671 | pub fn nftnl_set_nlmsg_build_payload(nlh: *mut nlmsghdr, s: *mut nftnl_set); 672 | 673 | pub fn nftnl_set_nlmsg_parse(nlh: *const nlmsghdr, s: *mut nftnl_set) -> c_int; 674 | 675 | pub fn nftnl_set_elems_nlmsg_parse(nlh: *const nlmsghdr, s: *mut nftnl_set) -> c_int; 676 | 677 | pub fn nftnl_set_snprintf( 678 | buf: *mut c_char, 679 | size: usize, 680 | s: *const nftnl_set, 681 | type_: u32, 682 | flags: u32, 683 | ) -> c_int; 684 | 685 | pub fn nftnl_set_fprintf(fp: *mut FILE, s: *const nftnl_set, type_: u32, flags: u32) -> c_int; 686 | } 687 | #[repr(C)] 688 | pub struct nftnl_set_list(c_void); 689 | 690 | extern "C" { 691 | pub fn nftnl_set_list_alloc() -> *mut nftnl_set_list; 692 | 693 | pub fn nftnl_set_list_free(list: *mut nftnl_set_list); 694 | 695 | pub fn nftnl_set_list_is_empty(list: *const nftnl_set_list) -> c_int; 696 | 697 | pub fn nftnl_set_list_add(s: *mut nftnl_set, list: *mut nftnl_set_list); 698 | 699 | pub fn nftnl_set_list_add_tail(s: *mut nftnl_set, list: *mut nftnl_set_list); 700 | 701 | pub fn nftnl_set_list_del(s: *mut nftnl_set); 702 | 703 | pub fn nftnl_set_list_foreach( 704 | set_list: *mut nftnl_set_list, 705 | cb: Option c_int>, 706 | data: *mut c_void, 707 | ) -> c_int; 708 | } 709 | #[repr(C)] 710 | pub struct nftnl_set_list_iter(c_void); 711 | 712 | extern "C" { 713 | pub fn nftnl_set_list_iter_create(l: *mut nftnl_set_list) -> *mut nftnl_set_list_iter; 714 | 715 | pub fn nftnl_set_list_iter_cur(iter: *mut nftnl_set_list_iter) -> *mut nftnl_set; 716 | 717 | pub fn nftnl_set_list_iter_next(iter: *mut nftnl_set_list_iter) -> *mut nftnl_set; 718 | 719 | pub fn nftnl_set_list_iter_destroy(iter: *const nftnl_set_list_iter); 720 | 721 | pub fn nftnl_set_parse( 722 | s: *mut nftnl_set, 723 | type_: nftnl_parse_type, 724 | data: *const c_char, 725 | err: *mut nftnl_parse_err, 726 | ) -> c_int; 727 | 728 | pub fn nftnl_set_parse_file( 729 | s: *mut nftnl_set, 730 | type_: nftnl_parse_type, 731 | fp: *mut FILE, 732 | err: *mut nftnl_parse_err, 733 | ) -> c_int; 734 | } 735 | pub const NFTNL_SET_ELEM_FLAGS: u32 = 0; 736 | pub const NFTNL_SET_ELEM_KEY: u32 = 1; 737 | pub const NFTNL_SET_ELEM_VERDICT: u32 = 2; 738 | pub const NFTNL_SET_ELEM_CHAIN: u32 = 3; 739 | pub const NFTNL_SET_ELEM_DATA: u32 = 4; 740 | pub const NFTNL_SET_ELEM_TIMEOUT: u32 = 5; 741 | pub const NFTNL_SET_ELEM_EXPIRATION: u32 = 6; 742 | pub const NFTNL_SET_ELEM_USERDATA: u32 = 7; 743 | pub const NFTNL_SET_ELEM_EXPR: u32 = 8; 744 | 745 | #[repr(C)] 746 | pub struct nftnl_set_elem(c_void); 747 | 748 | extern "C" { 749 | pub fn nftnl_set_elem_alloc() -> *mut nftnl_set_elem; 750 | 751 | pub fn nftnl_set_elem_free(s: *mut nftnl_set_elem); 752 | 753 | pub fn nftnl_set_elem_clone(elem: *mut nftnl_set_elem) -> *mut nftnl_set_elem; 754 | 755 | pub fn nftnl_set_elem_add(s: *mut nftnl_set, elem: *mut nftnl_set_elem); 756 | 757 | pub fn nftnl_set_elem_unset(s: *mut nftnl_set_elem, attr: u16); 758 | 759 | pub fn nftnl_set_elem_set( 760 | s: *mut nftnl_set_elem, 761 | attr: u16, 762 | data: *const c_void, 763 | data_len: u32, 764 | ); 765 | 766 | pub fn nftnl_set_elem_set_u32(s: *mut nftnl_set_elem, attr: u16, val: u32); 767 | 768 | pub fn nftnl_set_elem_set_u64(s: *mut nftnl_set_elem, attr: u16, val: u64); 769 | 770 | pub fn nftnl_set_elem_set_str(s: *mut nftnl_set_elem, attr: u16, str: *const c_char); 771 | 772 | pub fn nftnl_set_elem_get( 773 | s: *mut nftnl_set_elem, 774 | attr: u16, 775 | data_len: *mut u32, 776 | ) -> *const c_void; 777 | 778 | pub fn nftnl_set_elem_get_str(s: *mut nftnl_set_elem, attr: u16) -> *const c_char; 779 | 780 | pub fn nftnl_set_elem_get_u32(s: *mut nftnl_set_elem, attr: u16) -> u32; 781 | 782 | pub fn nftnl_set_elem_get_u64(s: *mut nftnl_set_elem, attr: u16) -> u64; 783 | 784 | pub fn nftnl_set_elem_is_set(s: *const nftnl_set_elem, attr: u16) -> bool; 785 | 786 | pub fn nftnl_set_elems_nlmsg_build_payload(nlh: *mut nlmsghdr, s: *mut nftnl_set); 787 | 788 | pub fn nftnl_set_elem_nlmsg_build_payload(nlh: *mut nlmsghdr, e: *mut nftnl_set_elem); 789 | 790 | pub fn nftnl_set_elem_parse( 791 | e: *mut nftnl_set_elem, 792 | type_: nftnl_parse_type, 793 | data: *const c_char, 794 | err: *mut nftnl_parse_err, 795 | ) -> c_int; 796 | 797 | pub fn nftnl_set_elem_parse_file( 798 | e: *mut nftnl_set_elem, 799 | type_: nftnl_parse_type, 800 | fp: *mut FILE, 801 | err: *mut nftnl_parse_err, 802 | ) -> c_int; 803 | 804 | pub fn nftnl_set_elem_snprintf( 805 | buf: *mut c_char, 806 | size: usize, 807 | s: *const nftnl_set_elem, 808 | type_: u32, 809 | flags: u32, 810 | ) -> c_int; 811 | 812 | pub fn nftnl_set_elem_fprintf( 813 | fp: *mut FILE, 814 | se: *mut nftnl_set_elem, 815 | type_: u32, 816 | flags: u32, 817 | ) -> c_int; 818 | 819 | pub fn nftnl_set_elem_foreach( 820 | s: *mut nftnl_set, 821 | cb: Option c_int>, 822 | data: *mut c_void, 823 | ) -> c_int; 824 | } 825 | #[repr(C)] 826 | pub struct nftnl_set_elems_iter(c_void); 827 | 828 | extern "C" { 829 | pub fn nftnl_set_elems_iter_create(s: *mut nftnl_set) -> *mut nftnl_set_elems_iter; 830 | 831 | pub fn nftnl_set_elems_iter_cur(iter: *mut nftnl_set_elems_iter) -> *mut nftnl_set_elem; 832 | 833 | pub fn nftnl_set_elems_iter_next(iter: *mut nftnl_set_elems_iter) -> *mut nftnl_set_elem; 834 | 835 | pub fn nftnl_set_elems_iter_destroy(iter: *mut nftnl_set_elems_iter); 836 | 837 | pub fn nftnl_set_elems_nlmsg_build_payload_iter( 838 | nlh: *mut nlmsghdr, 839 | iter: *mut nftnl_set_elems_iter, 840 | ) -> c_int; 841 | } 842 | #[repr(C)] 843 | pub struct nftnl_table(c_void); 844 | 845 | extern "C" { 846 | pub fn nftnl_table_alloc() -> *mut nftnl_table; 847 | 848 | pub fn nftnl_table_free(arg1: *const nftnl_table); 849 | } 850 | pub const NFTNL_TABLE_NAME: nftnl_table_attr = 0; 851 | pub const NFTNL_TABLE_FAMILY: nftnl_table_attr = 1; 852 | pub const NFTNL_TABLE_FLAGS: nftnl_table_attr = 2; 853 | pub const NFTNL_TABLE_USE: nftnl_table_attr = 3; 854 | pub const __NFTNL_TABLE_MAX: nftnl_table_attr = 4; 855 | pub type nftnl_table_attr = u32; 856 | extern "C" { 857 | pub fn nftnl_table_is_set(t: *const nftnl_table, attr: u16) -> bool; 858 | 859 | pub fn nftnl_table_unset(t: *mut nftnl_table, attr: u16); 860 | 861 | pub fn nftnl_table_set(t: *mut nftnl_table, attr: u16, data: *const c_void); 862 | 863 | pub fn nftnl_table_set_data(t: *mut nftnl_table, attr: u16, data: *const c_void, data_len: u32); 864 | 865 | pub fn nftnl_table_get(t: *const nftnl_table, attr: u16) -> *const c_void; 866 | 867 | pub fn nftnl_table_get_data( 868 | t: *const nftnl_table, 869 | attr: u16, 870 | data_len: *mut u32, 871 | ) -> *const c_void; 872 | 873 | pub fn nftnl_table_set_u8(t: *mut nftnl_table, attr: u16, data: u8); 874 | 875 | pub fn nftnl_table_set_u32(t: *mut nftnl_table, attr: u16, data: u32); 876 | 877 | pub fn nftnl_table_set_str(t: *mut nftnl_table, attr: u16, str: *const c_char); 878 | 879 | pub fn nftnl_table_get_u8(t: *const nftnl_table, attr: u16) -> u8; 880 | 881 | pub fn nftnl_table_get_u32(t: *const nftnl_table, attr: u16) -> u32; 882 | 883 | pub fn nftnl_table_get_str(t: *const nftnl_table, attr: u16) -> *const c_char; 884 | 885 | pub fn nftnl_table_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *const nftnl_table); 886 | 887 | pub fn nftnl_table_parse( 888 | t: *mut nftnl_table, 889 | type_: nftnl_parse_type, 890 | data: *const c_char, 891 | err: *mut nftnl_parse_err, 892 | ) -> c_int; 893 | 894 | pub fn nftnl_table_parse_file( 895 | t: *mut nftnl_table, 896 | type_: nftnl_parse_type, 897 | fp: *mut FILE, 898 | err: *mut nftnl_parse_err, 899 | ) -> c_int; 900 | 901 | pub fn nftnl_table_snprintf( 902 | buf: *mut c_char, 903 | size: usize, 904 | t: *const nftnl_table, 905 | type_: u32, 906 | flags: u32, 907 | ) -> c_int; 908 | 909 | pub fn nftnl_table_fprintf( 910 | fp: *mut FILE, 911 | t: *const nftnl_table, 912 | type_: u32, 913 | flags: u32, 914 | ) -> c_int; 915 | 916 | pub fn nftnl_table_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_table) -> c_int; 917 | } 918 | #[repr(C)] 919 | pub struct nftnl_table_list(c_void); 920 | 921 | extern "C" { 922 | pub fn nftnl_table_list_alloc() -> *mut nftnl_table_list; 923 | 924 | pub fn nftnl_table_list_free(list: *mut nftnl_table_list); 925 | 926 | pub fn nftnl_table_list_is_empty(list: *const nftnl_table_list) -> c_int; 927 | 928 | pub fn nftnl_table_list_foreach( 929 | table_list: *mut nftnl_table_list, 930 | cb: Option c_int>, 931 | data: *mut c_void, 932 | ) -> c_int; 933 | 934 | pub fn nftnl_table_list_add(r: *mut nftnl_table, list: *mut nftnl_table_list); 935 | 936 | pub fn nftnl_table_list_add_tail(r: *mut nftnl_table, list: *mut nftnl_table_list); 937 | 938 | pub fn nftnl_table_list_del(r: *mut nftnl_table); 939 | } 940 | #[repr(C)] 941 | pub struct nftnl_table_list_iter(c_void); 942 | 943 | extern "C" { 944 | pub fn nftnl_table_list_iter_create(l: *mut nftnl_table_list) -> *mut nftnl_table_list_iter; 945 | 946 | pub fn nftnl_table_list_iter_next(iter: *mut nftnl_table_list_iter) -> *mut nftnl_table; 947 | 948 | pub fn nftnl_table_list_iter_destroy(iter: *const nftnl_table_list_iter); 949 | } 950 | pub const NFTNL_TRACE_CHAIN: nftnl_trace_attr = 0; 951 | pub const NFTNL_TRACE_FAMILY: nftnl_trace_attr = 1; 952 | pub const NFTNL_TRACE_ID: nftnl_trace_attr = 2; 953 | pub const NFTNL_TRACE_IIF: nftnl_trace_attr = 3; 954 | pub const NFTNL_TRACE_IIFTYPE: nftnl_trace_attr = 4; 955 | pub const NFTNL_TRACE_JUMP_TARGET: nftnl_trace_attr = 5; 956 | pub const NFTNL_TRACE_OIF: nftnl_trace_attr = 6; 957 | pub const NFTNL_TRACE_OIFTYPE: nftnl_trace_attr = 7; 958 | pub const NFTNL_TRACE_MARK: nftnl_trace_attr = 8; 959 | pub const NFTNL_TRACE_LL_HEADER: nftnl_trace_attr = 9; 960 | pub const NFTNL_TRACE_NETWORK_HEADER: nftnl_trace_attr = 10; 961 | pub const NFTNL_TRACE_TRANSPORT_HEADER: nftnl_trace_attr = 11; 962 | pub const NFTNL_TRACE_TABLE: nftnl_trace_attr = 12; 963 | pub const NFTNL_TRACE_TYPE: nftnl_trace_attr = 13; 964 | pub const NFTNL_TRACE_RULE_HANDLE: nftnl_trace_attr = 14; 965 | pub const NFTNL_TRACE_VERDICT: nftnl_trace_attr = 15; 966 | pub const NFTNL_TRACE_NFPROTO: nftnl_trace_attr = 16; 967 | pub const NFTNL_TRACE_POLICY: nftnl_trace_attr = 17; 968 | pub const __NFTNL_TRACE_MAX: nftnl_trace_attr = 18; 969 | pub type nftnl_trace_attr = u32; 970 | #[repr(C)] 971 | pub struct nftnl_trace(c_void); 972 | 973 | extern "C" { 974 | pub fn nftnl_trace_alloc() -> *mut nftnl_trace; 975 | 976 | pub fn nftnl_trace_free(trace: *const nftnl_trace); 977 | 978 | pub fn nftnl_trace_is_set(trace: *const nftnl_trace, type_: u16) -> bool; 979 | 980 | pub fn nftnl_trace_get_data( 981 | trace: *const nftnl_trace, 982 | type_: u16, 983 | data_len: *mut u32, 984 | ) -> *const c_void; 985 | 986 | pub fn nftnl_trace_get_u16(trace: *const nftnl_trace, type_: u16) -> u16; 987 | 988 | pub fn nftnl_trace_get_u32(trace: *const nftnl_trace, type_: u16) -> u32; 989 | 990 | pub fn nftnl_trace_get_u64(trace: *const nftnl_trace, type_: u16) -> u64; 991 | 992 | pub fn nftnl_trace_get_str(trace: *const nftnl_trace, type_: u16) -> *const c_char; 993 | 994 | pub fn nftnl_trace_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_trace) -> c_int; 995 | } 996 | #[repr(C)] 997 | pub struct nftnl_udata(c_void); 998 | 999 | #[repr(C)] 1000 | pub struct nftnl_udata_buf(c_void); 1001 | 1002 | extern "C" { 1003 | pub fn nftnl_udata_buf_alloc(data_size: u32) -> *mut nftnl_udata_buf; 1004 | 1005 | pub fn nftnl_udata_buf_free(buf: *const nftnl_udata_buf); 1006 | 1007 | pub fn nftnl_udata_buf_len(buf: *const nftnl_udata_buf) -> u32; 1008 | 1009 | pub fn nftnl_udata_buf_data(buf: *const nftnl_udata_buf) -> *mut c_void; 1010 | 1011 | pub fn nftnl_udata_buf_put(buf: *mut nftnl_udata_buf, data: *const c_void, len: u32); 1012 | 1013 | pub fn nftnl_udata_start(buf: *const nftnl_udata_buf) -> *mut nftnl_udata; 1014 | 1015 | pub fn nftnl_udata_end(buf: *const nftnl_udata_buf) -> *mut nftnl_udata; 1016 | 1017 | pub fn nftnl_udata_put( 1018 | buf: *mut nftnl_udata_buf, 1019 | type_: u8, 1020 | len: u32, 1021 | value: *const c_void, 1022 | ) -> bool; 1023 | 1024 | pub fn nftnl_udata_put_strz(buf: *mut nftnl_udata_buf, type_: u8, strz: *const c_char) -> bool; 1025 | 1026 | pub fn nftnl_udata_type(attr: *const nftnl_udata) -> u8; 1027 | 1028 | pub fn nftnl_udata_len(attr: *const nftnl_udata) -> u8; 1029 | 1030 | pub fn nftnl_udata_get(attr: *const nftnl_udata) -> *mut c_void; 1031 | 1032 | pub fn nftnl_udata_next(attr: *const nftnl_udata) -> *mut nftnl_udata; 1033 | } 1034 | pub type nftnl_udata_cb_t = 1035 | Option c_int>; 1036 | extern "C" { 1037 | pub fn nftnl_udata_parse( 1038 | data: *const c_void, 1039 | data_len: u32, 1040 | cb: nftnl_udata_cb_t, 1041 | cb_data: *mut c_void, 1042 | ) -> c_int; 1043 | } 1044 | -------------------------------------------------------------------------------- /nftnl-sys/src/nftnl_1_0_7.rs: -------------------------------------------------------------------------------- 1 | // automatically generated by rust-bindgen 0.39.0 2 | 3 | use core::option::Option; 4 | use libc::{c_char, c_int, c_void, iovec, nlmsghdr, FILE}; 5 | 6 | #[repr(C)] 7 | pub struct nftnl_batch(c_void); 8 | 9 | extern "C" { 10 | pub fn nftnl_batch_alloc(pg_size: u32, pg_overrun_size: u32) -> *mut nftnl_batch; 11 | 12 | pub fn nftnl_batch_update(batch: *mut nftnl_batch) -> c_int; 13 | 14 | pub fn nftnl_batch_free(batch: *mut nftnl_batch); 15 | 16 | pub fn nftnl_batch_buffer(batch: *mut nftnl_batch) -> *mut c_void; 17 | 18 | pub fn nftnl_batch_buffer_len(batch: *mut nftnl_batch) -> u32; 19 | 20 | pub fn nftnl_batch_iovec_len(batch: *mut nftnl_batch) -> c_int; 21 | 22 | pub fn nftnl_batch_iovec(batch: *mut nftnl_batch, iov: *mut iovec, iovlen: u32); 23 | } 24 | pub const NFTNL_PARSE_EBADINPUT: u32 = 0; 25 | pub const NFTNL_PARSE_EMISSINGNODE: u32 = 1; 26 | pub const NFTNL_PARSE_EBADTYPE: u32 = 2; 27 | pub const NFTNL_PARSE_EOPNOTSUPP: u32 = 3; 28 | 29 | pub const NFTNL_OUTPUT_DEFAULT: nftnl_output_type = 0; 30 | pub const NFTNL_OUTPUT_XML: nftnl_output_type = 1; 31 | pub const NFTNL_OUTPUT_JSON: nftnl_output_type = 2; 32 | pub type nftnl_output_type = u32; 33 | pub const NFTNL_OF_EVENT_NEW: nftnl_output_flags = 1; 34 | pub const NFTNL_OF_EVENT_DEL: nftnl_output_flags = 2; 35 | pub const NFTNL_OF_EVENT_ANY: nftnl_output_flags = 3; 36 | pub type nftnl_output_flags = u32; 37 | pub const NFTNL_CMD_UNSPEC: nftnl_cmd_type = 0; 38 | pub const NFTNL_CMD_ADD: nftnl_cmd_type = 1; 39 | pub const NFTNL_CMD_INSERT: nftnl_cmd_type = 2; 40 | pub const NFTNL_CMD_DELETE: nftnl_cmd_type = 3; 41 | pub const NFTNL_CMD_REPLACE: nftnl_cmd_type = 4; 42 | pub const NFTNL_CMD_FLUSH: nftnl_cmd_type = 5; 43 | pub const NFTNL_CMD_MAX: nftnl_cmd_type = 6; 44 | pub type nftnl_cmd_type = u32; 45 | pub const NFTNL_PARSE_NONE: nftnl_parse_type = 0; 46 | pub const NFTNL_PARSE_XML: nftnl_parse_type = 1; 47 | pub const NFTNL_PARSE_JSON: nftnl_parse_type = 2; 48 | pub const NFTNL_PARSE_MAX: nftnl_parse_type = 3; 49 | pub type nftnl_parse_type = u32; 50 | #[repr(C)] 51 | pub struct nftnl_parse_err(c_void); 52 | 53 | extern "C" { 54 | pub fn nftnl_nlmsg_build_hdr( 55 | buf: *mut c_char, 56 | cmd: u16, 57 | family: u16, 58 | type_: u16, 59 | seq: u32, 60 | ) -> *mut nlmsghdr; 61 | 62 | pub fn nftnl_parse_err_alloc() -> *mut nftnl_parse_err; 63 | 64 | pub fn nftnl_parse_err_free(arg1: *mut nftnl_parse_err); 65 | 66 | pub fn nftnl_parse_perror(str: *const c_char, err: *mut nftnl_parse_err) -> c_int; 67 | 68 | pub fn nftnl_batch_is_supported() -> c_int; 69 | 70 | pub fn nftnl_batch_begin(buf: *mut c_char, seq: u32); 71 | 72 | pub fn nftnl_batch_end(buf: *mut c_char, seq: u32); 73 | } 74 | #[repr(C)] 75 | pub struct nftnl_chain(c_void); 76 | 77 | extern "C" { 78 | pub fn nftnl_chain_alloc() -> *mut nftnl_chain; 79 | 80 | pub fn nftnl_chain_free(arg1: *const nftnl_chain); 81 | } 82 | pub const NFTNL_CHAIN_NAME: nftnl_chain_attr = 0; 83 | pub const NFTNL_CHAIN_FAMILY: nftnl_chain_attr = 1; 84 | pub const NFTNL_CHAIN_TABLE: nftnl_chain_attr = 2; 85 | pub const NFTNL_CHAIN_HOOKNUM: nftnl_chain_attr = 3; 86 | pub const NFTNL_CHAIN_PRIO: nftnl_chain_attr = 4; 87 | pub const NFTNL_CHAIN_POLICY: nftnl_chain_attr = 5; 88 | pub const NFTNL_CHAIN_USE: nftnl_chain_attr = 6; 89 | pub const NFTNL_CHAIN_BYTES: nftnl_chain_attr = 7; 90 | pub const NFTNL_CHAIN_PACKETS: nftnl_chain_attr = 8; 91 | pub const NFTNL_CHAIN_HANDLE: nftnl_chain_attr = 9; 92 | pub const NFTNL_CHAIN_TYPE: nftnl_chain_attr = 10; 93 | pub const NFTNL_CHAIN_DEV: nftnl_chain_attr = 11; 94 | pub const __NFTNL_CHAIN_MAX: nftnl_chain_attr = 12; 95 | pub type nftnl_chain_attr = u32; 96 | extern "C" { 97 | pub fn nftnl_chain_is_set(c: *const nftnl_chain, attr: u16) -> bool; 98 | 99 | pub fn nftnl_chain_unset(c: *mut nftnl_chain, attr: u16); 100 | 101 | pub fn nftnl_chain_set(t: *mut nftnl_chain, attr: u16, data: *const c_void); 102 | 103 | pub fn nftnl_chain_set_data( 104 | t: *mut nftnl_chain, 105 | attr: u16, 106 | data: *const c_void, 107 | data_len: u32, 108 | ) -> c_int; 109 | 110 | pub fn nftnl_chain_set_u8(t: *mut nftnl_chain, attr: u16, data: u8); 111 | 112 | pub fn nftnl_chain_set_u32(t: *mut nftnl_chain, attr: u16, data: u32); 113 | 114 | pub fn nftnl_chain_set_s32(t: *mut nftnl_chain, attr: u16, data: i32); 115 | 116 | pub fn nftnl_chain_set_u64(t: *mut nftnl_chain, attr: u16, data: u64); 117 | 118 | pub fn nftnl_chain_set_str(t: *mut nftnl_chain, attr: u16, str: *const c_char) -> c_int; 119 | 120 | pub fn nftnl_chain_get(c: *const nftnl_chain, attr: u16) -> *const c_void; 121 | 122 | pub fn nftnl_chain_get_data( 123 | c: *const nftnl_chain, 124 | attr: u16, 125 | data_len: *mut u32, 126 | ) -> *const c_void; 127 | 128 | pub fn nftnl_chain_get_str(c: *const nftnl_chain, attr: u16) -> *const c_char; 129 | 130 | pub fn nftnl_chain_get_u8(c: *const nftnl_chain, attr: u16) -> u8; 131 | 132 | pub fn nftnl_chain_get_u32(c: *const nftnl_chain, attr: u16) -> u32; 133 | 134 | pub fn nftnl_chain_get_s32(c: *const nftnl_chain, attr: u16) -> i32; 135 | 136 | pub fn nftnl_chain_get_u64(c: *const nftnl_chain, attr: u16) -> u64; 137 | 138 | pub fn nftnl_chain_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *const nftnl_chain); 139 | 140 | pub fn nftnl_chain_parse( 141 | c: *mut nftnl_chain, 142 | type_: nftnl_parse_type, 143 | data: *const c_char, 144 | err: *mut nftnl_parse_err, 145 | ) -> c_int; 146 | 147 | pub fn nftnl_chain_parse_file( 148 | c: *mut nftnl_chain, 149 | type_: nftnl_parse_type, 150 | fp: *mut FILE, 151 | err: *mut nftnl_parse_err, 152 | ) -> c_int; 153 | 154 | pub fn nftnl_chain_snprintf( 155 | buf: *mut c_char, 156 | size: usize, 157 | t: *const nftnl_chain, 158 | type_: u32, 159 | flags: u32, 160 | ) -> c_int; 161 | 162 | pub fn nftnl_chain_fprintf( 163 | fp: *mut FILE, 164 | c: *const nftnl_chain, 165 | type_: u32, 166 | flags: u32, 167 | ) -> c_int; 168 | 169 | pub fn nftnl_chain_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_chain) -> c_int; 170 | } 171 | #[repr(C)] 172 | pub struct nftnl_chain_list(c_void); 173 | 174 | extern "C" { 175 | pub fn nftnl_chain_list_alloc() -> *mut nftnl_chain_list; 176 | 177 | pub fn nftnl_chain_list_free(list: *mut nftnl_chain_list); 178 | 179 | pub fn nftnl_chain_list_is_empty(list: *const nftnl_chain_list) -> c_int; 180 | 181 | pub fn nftnl_chain_list_foreach( 182 | chain_list: *mut nftnl_chain_list, 183 | cb: Option c_int>, 184 | data: *mut c_void, 185 | ) -> c_int; 186 | 187 | pub fn nftnl_chain_list_add(r: *mut nftnl_chain, list: *mut nftnl_chain_list); 188 | 189 | pub fn nftnl_chain_list_add_tail(r: *mut nftnl_chain, list: *mut nftnl_chain_list); 190 | 191 | pub fn nftnl_chain_list_del(c: *mut nftnl_chain); 192 | } 193 | #[repr(C)] 194 | pub struct nftnl_chain_list_iter(c_void); 195 | 196 | extern "C" { 197 | pub fn nftnl_chain_list_iter_create(l: *const nftnl_chain_list) -> *mut nftnl_chain_list_iter; 198 | 199 | pub fn nftnl_chain_list_iter_next(iter: *mut nftnl_chain_list_iter) -> *mut nftnl_chain; 200 | 201 | pub fn nftnl_chain_list_iter_destroy(iter: *mut nftnl_chain_list_iter); 202 | } 203 | #[repr(C)] 204 | pub struct nftnl_expr(c_void); 205 | 206 | pub const NFTNL_EXPR_NAME: u32 = 0; 207 | pub const NFTNL_EXPR_BASE: u32 = 1; 208 | 209 | extern "C" { 210 | pub fn nftnl_expr_alloc(name: *const c_char) -> *mut nftnl_expr; 211 | 212 | pub fn nftnl_expr_free(expr: *const nftnl_expr); 213 | 214 | pub fn nftnl_expr_is_set(expr: *const nftnl_expr, type_: u16) -> bool; 215 | 216 | pub fn nftnl_expr_set( 217 | expr: *mut nftnl_expr, 218 | type_: u16, 219 | data: *const c_void, 220 | data_len: u32, 221 | ) -> c_int; 222 | 223 | pub fn nftnl_expr_set_u8(expr: *mut nftnl_expr, type_: u16, data: u8); 224 | 225 | pub fn nftnl_expr_set_u16(expr: *mut nftnl_expr, type_: u16, data: u16); 226 | 227 | pub fn nftnl_expr_set_u32(expr: *mut nftnl_expr, type_: u16, data: u32); 228 | 229 | pub fn nftnl_expr_set_u64(expr: *mut nftnl_expr, type_: u16, data: u64); 230 | 231 | pub fn nftnl_expr_set_str(expr: *mut nftnl_expr, type_: u16, str: *const c_char) -> c_int; 232 | 233 | pub fn nftnl_expr_get(expr: *const nftnl_expr, type_: u16, data_len: *mut u32) 234 | -> *const c_void; 235 | 236 | pub fn nftnl_expr_get_u8(expr: *const nftnl_expr, type_: u16) -> u8; 237 | 238 | pub fn nftnl_expr_get_u16(expr: *const nftnl_expr, type_: u16) -> u16; 239 | 240 | pub fn nftnl_expr_get_u32(expr: *const nftnl_expr, type_: u16) -> u32; 241 | 242 | pub fn nftnl_expr_get_u64(expr: *const nftnl_expr, type_: u16) -> u64; 243 | 244 | pub fn nftnl_expr_get_str(expr: *const nftnl_expr, type_: u16) -> *const c_char; 245 | 246 | pub fn nftnl_expr_cmp(e1: *const nftnl_expr, e2: *const nftnl_expr) -> bool; 247 | 248 | pub fn nftnl_expr_snprintf( 249 | buf: *mut c_char, 250 | buflen: usize, 251 | expr: *const nftnl_expr, 252 | type_: u32, 253 | flags: u32, 254 | ) -> c_int; 255 | } 256 | pub const NFTNL_EXPR_PAYLOAD_DREG: u32 = 1; 257 | pub const NFTNL_EXPR_PAYLOAD_BASE: u32 = 2; 258 | pub const NFTNL_EXPR_PAYLOAD_OFFSET: u32 = 3; 259 | pub const NFTNL_EXPR_PAYLOAD_LEN: u32 = 4; 260 | pub const NFTNL_EXPR_PAYLOAD_SREG: u32 = 5; 261 | pub const NFTNL_EXPR_PAYLOAD_CSUM_TYPE: u32 = 6; 262 | pub const NFTNL_EXPR_PAYLOAD_CSUM_OFFSET: u32 = 7; 263 | pub const NFTNL_EXPR_PAYLOAD_FLAGS: u32 = 8; 264 | 265 | pub const NFTNL_EXPR_NG_DREG: u32 = 1; 266 | pub const NFTNL_EXPR_NG_MODULUS: u32 = 2; 267 | pub const NFTNL_EXPR_NG_TYPE: u32 = 3; 268 | pub const NFTNL_EXPR_NG_OFFSET: u32 = 4; 269 | 270 | pub const NFTNL_EXPR_META_KEY: u32 = 1; 271 | pub const NFTNL_EXPR_META_DREG: u32 = 2; 272 | pub const NFTNL_EXPR_META_SREG: u32 = 3; 273 | 274 | pub const NFTNL_EXPR_RT_KEY: u32 = 1; 275 | pub const NFTNL_EXPR_RT_DREG: u32 = 2; 276 | 277 | pub const NFTNL_EXPR_CMP_SREG: u32 = 1; 278 | pub const NFTNL_EXPR_CMP_OP: u32 = 2; 279 | pub const NFTNL_EXPR_CMP_DATA: u32 = 3; 280 | 281 | pub const NFTNL_EXPR_RANGE_SREG: u32 = 1; 282 | pub const NFTNL_EXPR_RANGE_OP: u32 = 2; 283 | pub const NFTNL_EXPR_RANGE_FROM_DATA: u32 = 3; 284 | pub const NFTNL_EXPR_RANGE_TO_DATA: u32 = 4; 285 | 286 | pub const NFTNL_EXPR_IMM_DREG: u32 = 1; 287 | pub const NFTNL_EXPR_IMM_DATA: u32 = 2; 288 | pub const NFTNL_EXPR_IMM_VERDICT: u32 = 3; 289 | pub const NFTNL_EXPR_IMM_CHAIN: u32 = 4; 290 | 291 | pub const NFTNL_EXPR_CTR_PACKETS: u32 = 1; 292 | pub const NFTNL_EXPR_CTR_BYTES: u32 = 2; 293 | 294 | pub const NFTNL_EXPR_BITWISE_SREG: u32 = 1; 295 | pub const NFTNL_EXPR_BITWISE_DREG: u32 = 2; 296 | pub const NFTNL_EXPR_BITWISE_LEN: u32 = 3; 297 | pub const NFTNL_EXPR_BITWISE_MASK: u32 = 4; 298 | pub const NFTNL_EXPR_BITWISE_XOR: u32 = 5; 299 | 300 | pub const NFTNL_EXPR_TG_NAME: u32 = 1; 301 | pub const NFTNL_EXPR_TG_REV: u32 = 2; 302 | pub const NFTNL_EXPR_TG_INFO: u32 = 3; 303 | 304 | pub const NFTNL_EXPR_MT_NAME: u32 = 1; 305 | pub const NFTNL_EXPR_MT_REV: u32 = 2; 306 | pub const NFTNL_EXPR_MT_INFO: u32 = 3; 307 | 308 | pub const NFTNL_EXPR_NAT_TYPE: u32 = 1; 309 | pub const NFTNL_EXPR_NAT_FAMILY: u32 = 2; 310 | pub const NFTNL_EXPR_NAT_REG_ADDR_MIN: u32 = 3; 311 | pub const NFTNL_EXPR_NAT_REG_ADDR_MAX: u32 = 4; 312 | pub const NFTNL_EXPR_NAT_REG_PROTO_MIN: u32 = 5; 313 | pub const NFTNL_EXPR_NAT_REG_PROTO_MAX: u32 = 6; 314 | pub const NFTNL_EXPR_NAT_FLAGS: u32 = 7; 315 | 316 | pub const NFTNL_EXPR_LOOKUP_SREG: u32 = 1; 317 | pub const NFTNL_EXPR_LOOKUP_DREG: u32 = 2; 318 | pub const NFTNL_EXPR_LOOKUP_SET: u32 = 3; 319 | pub const NFTNL_EXPR_LOOKUP_SET_ID: u32 = 4; 320 | pub const NFTNL_EXPR_LOOKUP_FLAGS: u32 = 5; 321 | 322 | pub const NFTNL_EXPR_DYNSET_SREG_KEY: u32 = 1; 323 | pub const NFTNL_EXPR_DYNSET_SREG_DATA: u32 = 2; 324 | pub const NFTNL_EXPR_DYNSET_OP: u32 = 3; 325 | pub const NFTNL_EXPR_DYNSET_TIMEOUT: u32 = 4; 326 | pub const NFTNL_EXPR_DYNSET_SET_NAME: u32 = 5; 327 | pub const NFTNL_EXPR_DYNSET_SET_ID: u32 = 6; 328 | pub const NFTNL_EXPR_DYNSET_EXPR: u32 = 7; 329 | 330 | pub const NFTNL_EXPR_LOG_PREFIX: u32 = 1; 331 | pub const NFTNL_EXPR_LOG_GROUP: u32 = 2; 332 | pub const NFTNL_EXPR_LOG_SNAPLEN: u32 = 3; 333 | pub const NFTNL_EXPR_LOG_QTHRESHOLD: u32 = 4; 334 | pub const NFTNL_EXPR_LOG_LEVEL: u32 = 5; 335 | pub const NFTNL_EXPR_LOG_FLAGS: u32 = 6; 336 | 337 | pub const NFTNL_EXPR_EXTHDR_DREG: u32 = 1; 338 | pub const NFTNL_EXPR_EXTHDR_TYPE: u32 = 2; 339 | pub const NFTNL_EXPR_EXTHDR_OFFSET: u32 = 3; 340 | pub const NFTNL_EXPR_EXTHDR_LEN: u32 = 4; 341 | 342 | pub const NFTNL_EXPR_CT_DREG: u32 = 1; 343 | pub const NFTNL_EXPR_CT_KEY: u32 = 2; 344 | pub const NFTNL_EXPR_CT_DIR: u32 = 3; 345 | pub const NFTNL_EXPR_CT_SREG: u32 = 4; 346 | 347 | pub const NFTNL_EXPR_BYTEORDER_DREG: u32 = 1; 348 | pub const NFTNL_EXPR_BYTEORDER_SREG: u32 = 2; 349 | pub const NFTNL_EXPR_BYTEORDER_OP: u32 = 3; 350 | pub const NFTNL_EXPR_BYTEORDER_LEN: u32 = 4; 351 | pub const NFTNL_EXPR_BYTEORDER_SIZE: u32 = 5; 352 | 353 | pub const NFTNL_EXPR_LIMIT_RATE: u32 = 1; 354 | pub const NFTNL_EXPR_LIMIT_UNIT: u32 = 2; 355 | pub const NFTNL_EXPR_LIMIT_BURST: u32 = 3; 356 | pub const NFTNL_EXPR_LIMIT_TYPE: u32 = 4; 357 | pub const NFTNL_EXPR_LIMIT_FLAGS: u32 = 5; 358 | 359 | pub const NFTNL_EXPR_REJECT_TYPE: u32 = 1; 360 | pub const NFTNL_EXPR_REJECT_CODE: u32 = 2; 361 | 362 | pub const NFTNL_EXPR_QUEUE_NUM: u32 = 1; 363 | pub const NFTNL_EXPR_QUEUE_TOTAL: u32 = 2; 364 | pub const NFTNL_EXPR_QUEUE_FLAGS: u32 = 3; 365 | pub const NFTNL_EXPR_QUEUE_SREG_QNUM: u32 = 4; 366 | 367 | pub const NFTNL_EXPR_QUOTA_BYTES: u32 = 1; 368 | pub const NFTNL_EXPR_QUOTA_FLAGS: u32 = 2; 369 | pub const NFTNL_EXPR_QUOTA_CONSUMED: u32 = 3; 370 | 371 | pub const NFTNL_EXPR_MASQ_FLAGS: u32 = 1; 372 | pub const NFTNL_EXPR_MASQ_REG_PROTO_MIN: u32 = 2; 373 | pub const NFTNL_EXPR_MASQ_REG_PROTO_MAX: u32 = 3; 374 | 375 | pub const NFTNL_EXPR_REDIR_REG_PROTO_MIN: u32 = 1; 376 | pub const NFTNL_EXPR_REDIR_REG_PROTO_MAX: u32 = 2; 377 | pub const NFTNL_EXPR_REDIR_FLAGS: u32 = 3; 378 | 379 | pub const NFTNL_EXPR_DUP_SREG_ADDR: u32 = 1; 380 | pub const NFTNL_EXPR_DUP_SREG_DEV: u32 = 2; 381 | 382 | pub const NFTNL_EXPR_FWD_SREG_DEV: u32 = 1; 383 | 384 | pub const NFTNL_EXPR_HASH_SREG: u32 = 1; 385 | pub const NFTNL_EXPR_HASH_DREG: u32 = 2; 386 | pub const NFTNL_EXPR_HASH_LEN: u32 = 3; 387 | pub const NFTNL_EXPR_HASH_MODULUS: u32 = 4; 388 | pub const NFTNL_EXPR_HASH_SEED: u32 = 5; 389 | pub const NFTNL_EXPR_HASH_OFFSET: u32 = 6; 390 | 391 | pub const NFTNL_EXPR_FIB_DREG: u32 = 1; 392 | pub const NFTNL_EXPR_FIB_RESULT: u32 = 2; 393 | pub const NFTNL_EXPR_FIB_FLAGS: u32 = 3; 394 | 395 | pub const NFTNL_EXPR_OBJREF_IMM_TYPE: u32 = 1; 396 | pub const NFTNL_EXPR_OBJREF_IMM_NAME: u32 = 2; 397 | pub const NFTNL_EXPR_OBJREF_SET_SREG: u32 = 3; 398 | pub const NFTNL_EXPR_OBJREF_SET_NAME: u32 = 4; 399 | pub const NFTNL_EXPR_OBJREF_SET_ID: u32 = 5; 400 | 401 | #[repr(C)] 402 | pub struct nftnl_gen(c_void); 403 | 404 | extern "C" { 405 | pub fn nftnl_gen_alloc() -> *mut nftnl_gen; 406 | 407 | pub fn nftnl_gen_free(arg1: *const nftnl_gen); 408 | } 409 | pub const NFTNL_GEN_ID: u32 = 0; 410 | pub const __NFTNL_GEN_MAX: u32 = 1; 411 | 412 | extern "C" { 413 | pub fn nftnl_gen_is_set(gen: *const nftnl_gen, attr: u16) -> bool; 414 | 415 | pub fn nftnl_gen_unset(gen: *mut nftnl_gen, attr: u16); 416 | 417 | pub fn nftnl_gen_set(gen: *mut nftnl_gen, attr: u16, data: *const c_void) -> c_int; 418 | 419 | pub fn nftnl_gen_set_data( 420 | gen: *mut nftnl_gen, 421 | attr: u16, 422 | data: *const c_void, 423 | data_len: u32, 424 | ) -> c_int; 425 | 426 | pub fn nftnl_gen_get(gen: *const nftnl_gen, attr: u16) -> *const c_void; 427 | 428 | pub fn nftnl_gen_get_data( 429 | gen: *const nftnl_gen, 430 | attr: u16, 431 | data_len: *mut u32, 432 | ) -> *const c_void; 433 | 434 | pub fn nftnl_gen_set_u32(gen: *mut nftnl_gen, attr: u16, data: u32); 435 | 436 | pub fn nftnl_gen_get_u32(gen: *const nftnl_gen, attr: u16) -> u32; 437 | 438 | pub fn nftnl_gen_nlmsg_parse(nlh: *const nlmsghdr, gen: *mut nftnl_gen) -> c_int; 439 | 440 | pub fn nftnl_gen_snprintf( 441 | buf: *mut c_char, 442 | size: usize, 443 | gen: *const nftnl_gen, 444 | type_: u32, 445 | flags: u32, 446 | ) -> c_int; 447 | 448 | pub fn nftnl_gen_fprintf(fp: *mut FILE, gen: *const nftnl_gen, type_: u32, flags: u32) 449 | -> c_int; 450 | } 451 | pub const NFTNL_OBJ_TABLE: u32 = 0; 452 | pub const NFTNL_OBJ_NAME: u32 = 1; 453 | pub const NFTNL_OBJ_TYPE: u32 = 2; 454 | pub const NFTNL_OBJ_FAMILY: u32 = 3; 455 | pub const NFTNL_OBJ_USE: u32 = 4; 456 | pub const NFTNL_OBJ_BASE: u32 = 16; 457 | pub const __NFTNL_OBJ_MAX: u32 = 17; 458 | 459 | pub const NFTNL_OBJ_CTR_PKTS: u32 = 16; 460 | pub const NFTNL_OBJ_CTR_BYTES: u32 = 17; 461 | 462 | pub const NFTNL_OBJ_QUOTA_BYTES: u32 = 16; 463 | pub const NFTNL_OBJ_QUOTA_CONSUMED: u32 = 17; 464 | pub const NFTNL_OBJ_QUOTA_FLAGS: u32 = 18; 465 | 466 | #[repr(C)] 467 | pub struct nftnl_obj(c_void); 468 | 469 | extern "C" { 470 | pub fn nftnl_obj_alloc() -> *mut nftnl_obj; 471 | 472 | pub fn nftnl_obj_free(ne: *const nftnl_obj); 473 | 474 | pub fn nftnl_obj_is_set(ne: *const nftnl_obj, attr: u16) -> bool; 475 | 476 | pub fn nftnl_obj_unset(ne: *mut nftnl_obj, attr: u16); 477 | 478 | pub fn nftnl_obj_set_data(ne: *mut nftnl_obj, attr: u16, data: *const c_void, data_len: u32); 479 | 480 | pub fn nftnl_obj_set(ne: *mut nftnl_obj, attr: u16, data: *const c_void); 481 | 482 | pub fn nftnl_obj_set_u32(ne: *mut nftnl_obj, attr: u16, val: u32); 483 | 484 | pub fn nftnl_obj_set_u64(obj: *mut nftnl_obj, attr: u16, val: u64); 485 | 486 | pub fn nftnl_obj_set_str(ne: *mut nftnl_obj, attr: u16, str: *const c_char); 487 | 488 | pub fn nftnl_obj_get_data(ne: *mut nftnl_obj, attr: u16, data_len: *mut u32) -> *const c_void; 489 | 490 | pub fn nftnl_obj_get(ne: *mut nftnl_obj, attr: u16) -> *const c_void; 491 | 492 | pub fn nftnl_obj_get_u32(ne: *mut nftnl_obj, attr: u16) -> u32; 493 | 494 | pub fn nftnl_obj_get_u64(obj: *mut nftnl_obj, attr: u16) -> u64; 495 | 496 | pub fn nftnl_obj_get_str(ne: *mut nftnl_obj, attr: u16) -> *const c_char; 497 | 498 | pub fn nftnl_obj_nlmsg_build_payload(nlh: *mut nlmsghdr, ne: *const nftnl_obj); 499 | 500 | pub fn nftnl_obj_nlmsg_parse(nlh: *const nlmsghdr, ne: *mut nftnl_obj) -> c_int; 501 | 502 | pub fn nftnl_obj_parse( 503 | ne: *mut nftnl_obj, 504 | type_: nftnl_parse_type, 505 | data: *const c_char, 506 | err: *mut nftnl_parse_err, 507 | ) -> c_int; 508 | 509 | pub fn nftnl_obj_parse_file( 510 | ne: *mut nftnl_obj, 511 | type_: nftnl_parse_type, 512 | fp: *mut FILE, 513 | err: *mut nftnl_parse_err, 514 | ) -> c_int; 515 | 516 | pub fn nftnl_obj_snprintf( 517 | buf: *mut c_char, 518 | size: usize, 519 | ne: *const nftnl_obj, 520 | type_: u32, 521 | flags: u32, 522 | ) -> c_int; 523 | 524 | pub fn nftnl_obj_fprintf(fp: *mut FILE, ne: *const nftnl_obj, type_: u32, flags: u32) -> c_int; 525 | } 526 | #[repr(C)] 527 | pub struct nftnl_obj_list(c_void); 528 | 529 | extern "C" { 530 | pub fn nftnl_obj_list_alloc() -> *mut nftnl_obj_list; 531 | 532 | pub fn nftnl_obj_list_free(list: *mut nftnl_obj_list); 533 | 534 | pub fn nftnl_obj_list_is_empty(list: *mut nftnl_obj_list) -> c_int; 535 | 536 | pub fn nftnl_obj_list_add(r: *mut nftnl_obj, list: *mut nftnl_obj_list); 537 | 538 | pub fn nftnl_obj_list_add_tail(r: *mut nftnl_obj, list: *mut nftnl_obj_list); 539 | 540 | pub fn nftnl_obj_list_del(t: *mut nftnl_obj); 541 | 542 | pub fn nftnl_obj_list_foreach( 543 | table_list: *mut nftnl_obj_list, 544 | cb: Option c_int>, 545 | data: *mut c_void, 546 | ) -> c_int; 547 | } 548 | #[repr(C)] 549 | pub struct nftnl_obj_list_iter(c_void); 550 | 551 | extern "C" { 552 | pub fn nftnl_obj_list_iter_create(l: *mut nftnl_obj_list) -> *mut nftnl_obj_list_iter; 553 | 554 | pub fn nftnl_obj_list_iter_next(iter: *mut nftnl_obj_list_iter) -> *mut nftnl_obj; 555 | 556 | pub fn nftnl_obj_list_iter_destroy(iter: *mut nftnl_obj_list_iter); 557 | } 558 | #[repr(C)] 559 | pub struct nftnl_rule(c_void); 560 | 561 | extern "C" { 562 | pub fn nftnl_rule_alloc() -> *mut nftnl_rule; 563 | 564 | pub fn nftnl_rule_free(arg1: *const nftnl_rule); 565 | } 566 | pub const NFTNL_RULE_FAMILY: nftnl_rule_attr = 0; 567 | pub const NFTNL_RULE_TABLE: nftnl_rule_attr = 1; 568 | pub const NFTNL_RULE_CHAIN: nftnl_rule_attr = 2; 569 | pub const NFTNL_RULE_HANDLE: nftnl_rule_attr = 3; 570 | pub const NFTNL_RULE_COMPAT_PROTO: nftnl_rule_attr = 4; 571 | pub const NFTNL_RULE_COMPAT_FLAGS: nftnl_rule_attr = 5; 572 | pub const NFTNL_RULE_POSITION: nftnl_rule_attr = 6; 573 | pub const NFTNL_RULE_USERDATA: nftnl_rule_attr = 7; 574 | pub const __NFTNL_RULE_MAX: nftnl_rule_attr = 8; 575 | pub type nftnl_rule_attr = u32; 576 | extern "C" { 577 | pub fn nftnl_rule_unset(r: *mut nftnl_rule, attr: u16); 578 | 579 | pub fn nftnl_rule_is_set(r: *const nftnl_rule, attr: u16) -> bool; 580 | 581 | pub fn nftnl_rule_set(r: *mut nftnl_rule, attr: u16, data: *const c_void) -> c_int; 582 | 583 | pub fn nftnl_rule_set_data( 584 | r: *mut nftnl_rule, 585 | attr: u16, 586 | data: *const c_void, 587 | data_len: u32, 588 | ) -> c_int; 589 | 590 | pub fn nftnl_rule_set_u32(r: *mut nftnl_rule, attr: u16, val: u32); 591 | 592 | pub fn nftnl_rule_set_u64(r: *mut nftnl_rule, attr: u16, val: u64); 593 | 594 | pub fn nftnl_rule_set_str(r: *mut nftnl_rule, attr: u16, str: *const c_char) -> c_int; 595 | 596 | pub fn nftnl_rule_get(r: *const nftnl_rule, attr: u16) -> *const c_void; 597 | 598 | pub fn nftnl_rule_get_data( 599 | r: *const nftnl_rule, 600 | attr: u16, 601 | data_len: *mut u32, 602 | ) -> *const c_void; 603 | 604 | pub fn nftnl_rule_get_str(r: *const nftnl_rule, attr: u16) -> *const c_char; 605 | 606 | pub fn nftnl_rule_get_u8(r: *const nftnl_rule, attr: u16) -> u8; 607 | 608 | pub fn nftnl_rule_get_u32(r: *const nftnl_rule, attr: u16) -> u32; 609 | 610 | pub fn nftnl_rule_get_u64(r: *const nftnl_rule, attr: u16) -> u64; 611 | 612 | pub fn nftnl_rule_add_expr(r: *mut nftnl_rule, expr: *mut nftnl_expr); 613 | 614 | pub fn nftnl_rule_cmp(r1: *const nftnl_rule, r2: *const nftnl_rule) -> bool; 615 | 616 | pub fn nftnl_rule_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *mut nftnl_rule); 617 | 618 | pub fn nftnl_rule_parse( 619 | r: *mut nftnl_rule, 620 | type_: nftnl_parse_type, 621 | data: *const c_char, 622 | err: *mut nftnl_parse_err, 623 | ) -> c_int; 624 | 625 | pub fn nftnl_rule_parse_file( 626 | r: *mut nftnl_rule, 627 | type_: nftnl_parse_type, 628 | fp: *mut FILE, 629 | err: *mut nftnl_parse_err, 630 | ) -> c_int; 631 | 632 | pub fn nftnl_rule_snprintf( 633 | buf: *mut c_char, 634 | size: usize, 635 | t: *const nftnl_rule, 636 | type_: u32, 637 | flags: u32, 638 | ) -> c_int; 639 | 640 | pub fn nftnl_rule_fprintf(fp: *mut FILE, r: *const nftnl_rule, type_: u32, flags: u32) 641 | -> c_int; 642 | 643 | pub fn nftnl_rule_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_rule) -> c_int; 644 | 645 | pub fn nftnl_expr_foreach( 646 | r: *mut nftnl_rule, 647 | cb: Option c_int>, 648 | data: *mut c_void, 649 | ) -> c_int; 650 | } 651 | #[repr(C)] 652 | pub struct nftnl_expr_iter(c_void); 653 | 654 | extern "C" { 655 | pub fn nftnl_expr_iter_create(r: *const nftnl_rule) -> *mut nftnl_expr_iter; 656 | 657 | pub fn nftnl_expr_iter_next(iter: *mut nftnl_expr_iter) -> *mut nftnl_expr; 658 | 659 | pub fn nftnl_expr_iter_destroy(iter: *mut nftnl_expr_iter); 660 | } 661 | #[repr(C)] 662 | pub struct nftnl_rule_list(c_void); 663 | 664 | extern "C" { 665 | pub fn nftnl_rule_list_alloc() -> *mut nftnl_rule_list; 666 | 667 | pub fn nftnl_rule_list_free(list: *mut nftnl_rule_list); 668 | 669 | pub fn nftnl_rule_list_is_empty(list: *const nftnl_rule_list) -> c_int; 670 | 671 | pub fn nftnl_rule_list_add(r: *mut nftnl_rule, list: *mut nftnl_rule_list); 672 | 673 | pub fn nftnl_rule_list_add_tail(r: *mut nftnl_rule, list: *mut nftnl_rule_list); 674 | 675 | pub fn nftnl_rule_list_del(r: *mut nftnl_rule); 676 | 677 | pub fn nftnl_rule_list_foreach( 678 | rule_list: *mut nftnl_rule_list, 679 | cb: Option c_int>, 680 | data: *mut c_void, 681 | ) -> c_int; 682 | } 683 | #[repr(C)] 684 | pub struct nftnl_rule_list_iter(c_void); 685 | 686 | extern "C" { 687 | pub fn nftnl_rule_list_iter_create(l: *const nftnl_rule_list) -> *mut nftnl_rule_list_iter; 688 | 689 | pub fn nftnl_rule_list_iter_cur(iter: *mut nftnl_rule_list_iter) -> *mut nftnl_rule; 690 | 691 | pub fn nftnl_rule_list_iter_next(iter: *mut nftnl_rule_list_iter) -> *mut nftnl_rule; 692 | 693 | pub fn nftnl_rule_list_iter_destroy(iter: *const nftnl_rule_list_iter); 694 | } 695 | #[repr(C)] 696 | pub struct nftnl_ruleset(c_void); 697 | 698 | extern "C" { 699 | pub fn nftnl_ruleset_alloc() -> *mut nftnl_ruleset; 700 | 701 | pub fn nftnl_ruleset_free(r: *const nftnl_ruleset); 702 | } 703 | pub const NFTNL_RULESET_TABLELIST: u32 = 0; 704 | pub const NFTNL_RULESET_CHAINLIST: u32 = 1; 705 | pub const NFTNL_RULESET_SETLIST: u32 = 2; 706 | pub const NFTNL_RULESET_RULELIST: u32 = 3; 707 | 708 | pub const NFTNL_RULESET_UNSPEC: nftnl_ruleset_type = 0; 709 | pub const NFTNL_RULESET_RULESET: nftnl_ruleset_type = 1; 710 | pub const NFTNL_RULESET_TABLE: nftnl_ruleset_type = 2; 711 | pub const NFTNL_RULESET_CHAIN: nftnl_ruleset_type = 3; 712 | pub const NFTNL_RULESET_RULE: nftnl_ruleset_type = 4; 713 | pub const NFTNL_RULESET_SET: nftnl_ruleset_type = 5; 714 | pub const NFTNL_RULESET_SET_ELEMS: nftnl_ruleset_type = 6; 715 | pub type nftnl_ruleset_type = u32; 716 | extern "C" { 717 | pub fn nftnl_ruleset_is_set(r: *const nftnl_ruleset, attr: u16) -> bool; 718 | 719 | pub fn nftnl_ruleset_unset(r: *mut nftnl_ruleset, attr: u16); 720 | 721 | pub fn nftnl_ruleset_set(r: *mut nftnl_ruleset, attr: u16, data: *mut c_void); 722 | 723 | pub fn nftnl_ruleset_get(r: *const nftnl_ruleset, attr: u16) -> *mut c_void; 724 | } 725 | pub const NFTNL_RULESET_CTX_CMD: u32 = 0; 726 | pub const NFTNL_RULESET_CTX_TYPE: u32 = 1; 727 | pub const NFTNL_RULESET_CTX_TABLE: u32 = 2; 728 | pub const NFTNL_RULESET_CTX_CHAIN: u32 = 3; 729 | pub const NFTNL_RULESET_CTX_RULE: u32 = 4; 730 | pub const NFTNL_RULESET_CTX_SET: u32 = 5; 731 | pub const NFTNL_RULESET_CTX_DATA: u32 = 6; 732 | 733 | #[repr(C)] 734 | pub struct nftnl_parse_ctx(c_void); 735 | 736 | extern "C" { 737 | pub fn nftnl_ruleset_ctx_free(ctx: *const nftnl_parse_ctx); 738 | 739 | pub fn nftnl_ruleset_ctx_is_set(ctx: *const nftnl_parse_ctx, attr: u16) -> bool; 740 | 741 | pub fn nftnl_ruleset_ctx_get(ctx: *const nftnl_parse_ctx, attr: u16) -> *mut c_void; 742 | 743 | pub fn nftnl_ruleset_ctx_get_u32(ctx: *const nftnl_parse_ctx, attr: u16) -> u32; 744 | 745 | pub fn nftnl_ruleset_parse_file_cb( 746 | type_: nftnl_parse_type, 747 | fp: *mut FILE, 748 | err: *mut nftnl_parse_err, 749 | data: *mut c_void, 750 | cb: Option c_int>, 751 | ) -> c_int; 752 | 753 | pub fn nftnl_ruleset_parse_buffer_cb( 754 | type_: nftnl_parse_type, 755 | buffer: *const c_char, 756 | err: *mut nftnl_parse_err, 757 | data: *mut c_void, 758 | cb: Option c_int>, 759 | ) -> c_int; 760 | 761 | pub fn nftnl_ruleset_parse( 762 | rs: *mut nftnl_ruleset, 763 | type_: nftnl_parse_type, 764 | data: *const c_char, 765 | err: *mut nftnl_parse_err, 766 | ) -> c_int; 767 | 768 | pub fn nftnl_ruleset_parse_file( 769 | rs: *mut nftnl_ruleset, 770 | type_: nftnl_parse_type, 771 | fp: *mut FILE, 772 | err: *mut nftnl_parse_err, 773 | ) -> c_int; 774 | 775 | pub fn nftnl_ruleset_snprintf( 776 | buf: *mut c_char, 777 | size: usize, 778 | rs: *const nftnl_ruleset, 779 | type_: u32, 780 | flags: u32, 781 | ) -> c_int; 782 | 783 | pub fn nftnl_ruleset_fprintf( 784 | fp: *mut FILE, 785 | rs: *const nftnl_ruleset, 786 | type_: u32, 787 | flags: u32, 788 | ) -> c_int; 789 | } 790 | pub const NFTNL_SET_TABLE: nftnl_set_attr = 0; 791 | pub const NFTNL_SET_NAME: nftnl_set_attr = 1; 792 | pub const NFTNL_SET_FLAGS: nftnl_set_attr = 2; 793 | pub const NFTNL_SET_KEY_TYPE: nftnl_set_attr = 3; 794 | pub const NFTNL_SET_KEY_LEN: nftnl_set_attr = 4; 795 | pub const NFTNL_SET_DATA_TYPE: nftnl_set_attr = 5; 796 | pub const NFTNL_SET_DATA_LEN: nftnl_set_attr = 6; 797 | pub const NFTNL_SET_FAMILY: nftnl_set_attr = 7; 798 | pub const NFTNL_SET_ID: nftnl_set_attr = 8; 799 | pub const NFTNL_SET_POLICY: nftnl_set_attr = 9; 800 | pub const NFTNL_SET_DESC_SIZE: nftnl_set_attr = 10; 801 | pub const NFTNL_SET_TIMEOUT: nftnl_set_attr = 11; 802 | pub const NFTNL_SET_GC_INTERVAL: nftnl_set_attr = 12; 803 | pub const NFTNL_SET_USERDATA: nftnl_set_attr = 13; 804 | pub const NFTNL_SET_OBJ_TYPE: nftnl_set_attr = 14; 805 | pub const __NFTNL_SET_MAX: nftnl_set_attr = 15; 806 | pub type nftnl_set_attr = u32; 807 | #[repr(C)] 808 | pub struct nftnl_set(c_void); 809 | 810 | extern "C" { 811 | pub fn nftnl_set_alloc() -> *mut nftnl_set; 812 | 813 | pub fn nftnl_set_free(s: *const nftnl_set); 814 | 815 | pub fn nftnl_set_clone(set: *const nftnl_set) -> *mut nftnl_set; 816 | 817 | pub fn nftnl_set_is_set(s: *const nftnl_set, attr: u16) -> bool; 818 | 819 | pub fn nftnl_set_unset(s: *mut nftnl_set, attr: u16); 820 | 821 | pub fn nftnl_set_set(s: *mut nftnl_set, attr: u16, data: *const c_void) -> c_int; 822 | 823 | pub fn nftnl_set_set_data( 824 | s: *mut nftnl_set, 825 | attr: u16, 826 | data: *const c_void, 827 | data_len: u32, 828 | ) -> c_int; 829 | 830 | pub fn nftnl_set_set_u32(s: *mut nftnl_set, attr: u16, val: u32); 831 | 832 | pub fn nftnl_set_set_u64(s: *mut nftnl_set, attr: u16, val: u64); 833 | 834 | pub fn nftnl_set_set_str(s: *mut nftnl_set, attr: u16, str: *const c_char) -> c_int; 835 | 836 | pub fn nftnl_set_get(s: *const nftnl_set, attr: u16) -> *const c_void; 837 | 838 | pub fn nftnl_set_get_data(s: *const nftnl_set, attr: u16, data_len: *mut u32) -> *const c_void; 839 | 840 | pub fn nftnl_set_get_str(s: *const nftnl_set, attr: u16) -> *const c_char; 841 | 842 | pub fn nftnl_set_get_u32(s: *const nftnl_set, attr: u16) -> u32; 843 | 844 | pub fn nftnl_set_get_u64(s: *const nftnl_set, attr: u16) -> u64; 845 | 846 | pub fn nftnl_set_nlmsg_build_payload(nlh: *mut nlmsghdr, s: *mut nftnl_set); 847 | 848 | pub fn nftnl_set_nlmsg_parse(nlh: *const nlmsghdr, s: *mut nftnl_set) -> c_int; 849 | 850 | pub fn nftnl_set_elems_nlmsg_parse(nlh: *const nlmsghdr, s: *mut nftnl_set) -> c_int; 851 | 852 | pub fn nftnl_set_snprintf( 853 | buf: *mut c_char, 854 | size: usize, 855 | s: *const nftnl_set, 856 | type_: u32, 857 | flags: u32, 858 | ) -> c_int; 859 | 860 | pub fn nftnl_set_fprintf(fp: *mut FILE, s: *const nftnl_set, type_: u32, flags: u32) -> c_int; 861 | } 862 | #[repr(C)] 863 | pub struct nftnl_set_list(c_void); 864 | 865 | extern "C" { 866 | pub fn nftnl_set_list_alloc() -> *mut nftnl_set_list; 867 | 868 | pub fn nftnl_set_list_free(list: *mut nftnl_set_list); 869 | 870 | pub fn nftnl_set_list_is_empty(list: *const nftnl_set_list) -> c_int; 871 | 872 | pub fn nftnl_set_list_add(s: *mut nftnl_set, list: *mut nftnl_set_list); 873 | 874 | pub fn nftnl_set_list_add_tail(s: *mut nftnl_set, list: *mut nftnl_set_list); 875 | 876 | pub fn nftnl_set_list_del(s: *mut nftnl_set); 877 | 878 | pub fn nftnl_set_list_foreach( 879 | set_list: *mut nftnl_set_list, 880 | cb: Option c_int>, 881 | data: *mut c_void, 882 | ) -> c_int; 883 | } 884 | #[repr(C)] 885 | pub struct nftnl_set_list_iter(c_void); 886 | 887 | extern "C" { 888 | pub fn nftnl_set_list_iter_create(l: *const nftnl_set_list) -> *mut nftnl_set_list_iter; 889 | 890 | pub fn nftnl_set_list_iter_cur(iter: *const nftnl_set_list_iter) -> *mut nftnl_set; 891 | 892 | pub fn nftnl_set_list_iter_next(iter: *mut nftnl_set_list_iter) -> *mut nftnl_set; 893 | 894 | pub fn nftnl_set_list_iter_destroy(iter: *const nftnl_set_list_iter); 895 | 896 | pub fn nftnl_set_parse( 897 | s: *mut nftnl_set, 898 | type_: nftnl_parse_type, 899 | data: *const c_char, 900 | err: *mut nftnl_parse_err, 901 | ) -> c_int; 902 | 903 | pub fn nftnl_set_parse_file( 904 | s: *mut nftnl_set, 905 | type_: nftnl_parse_type, 906 | fp: *mut FILE, 907 | err: *mut nftnl_parse_err, 908 | ) -> c_int; 909 | } 910 | pub const NFTNL_SET_ELEM_FLAGS: u32 = 0; 911 | pub const NFTNL_SET_ELEM_KEY: u32 = 1; 912 | pub const NFTNL_SET_ELEM_VERDICT: u32 = 2; 913 | pub const NFTNL_SET_ELEM_CHAIN: u32 = 3; 914 | pub const NFTNL_SET_ELEM_DATA: u32 = 4; 915 | pub const NFTNL_SET_ELEM_TIMEOUT: u32 = 5; 916 | pub const NFTNL_SET_ELEM_EXPIRATION: u32 = 6; 917 | pub const NFTNL_SET_ELEM_USERDATA: u32 = 7; 918 | pub const NFTNL_SET_ELEM_EXPR: u32 = 8; 919 | pub const NFTNL_SET_ELEM_OBJREF: u32 = 9; 920 | 921 | #[repr(C)] 922 | pub struct nftnl_set_elem(c_void); 923 | 924 | extern "C" { 925 | pub fn nftnl_set_elem_alloc() -> *mut nftnl_set_elem; 926 | 927 | pub fn nftnl_set_elem_free(s: *mut nftnl_set_elem); 928 | 929 | pub fn nftnl_set_elem_clone(elem: *mut nftnl_set_elem) -> *mut nftnl_set_elem; 930 | 931 | pub fn nftnl_set_elem_add(s: *mut nftnl_set, elem: *mut nftnl_set_elem); 932 | 933 | pub fn nftnl_set_elem_unset(s: *mut nftnl_set_elem, attr: u16); 934 | 935 | pub fn nftnl_set_elem_set( 936 | s: *mut nftnl_set_elem, 937 | attr: u16, 938 | data: *const c_void, 939 | data_len: u32, 940 | ) -> c_int; 941 | 942 | pub fn nftnl_set_elem_set_u32(s: *mut nftnl_set_elem, attr: u16, val: u32); 943 | 944 | pub fn nftnl_set_elem_set_u64(s: *mut nftnl_set_elem, attr: u16, val: u64); 945 | 946 | pub fn nftnl_set_elem_set_str(s: *mut nftnl_set_elem, attr: u16, str: *const c_char) -> c_int; 947 | 948 | pub fn nftnl_set_elem_get( 949 | s: *mut nftnl_set_elem, 950 | attr: u16, 951 | data_len: *mut u32, 952 | ) -> *const c_void; 953 | 954 | pub fn nftnl_set_elem_get_str(s: *mut nftnl_set_elem, attr: u16) -> *const c_char; 955 | 956 | pub fn nftnl_set_elem_get_u32(s: *mut nftnl_set_elem, attr: u16) -> u32; 957 | 958 | pub fn nftnl_set_elem_get_u64(s: *mut nftnl_set_elem, attr: u16) -> u64; 959 | 960 | pub fn nftnl_set_elem_is_set(s: *const nftnl_set_elem, attr: u16) -> bool; 961 | 962 | pub fn nftnl_set_elems_nlmsg_build_payload(nlh: *mut nlmsghdr, s: *mut nftnl_set); 963 | 964 | pub fn nftnl_set_elem_nlmsg_build_payload(nlh: *mut nlmsghdr, e: *mut nftnl_set_elem); 965 | 966 | pub fn nftnl_set_elem_parse( 967 | e: *mut nftnl_set_elem, 968 | type_: nftnl_parse_type, 969 | data: *const c_char, 970 | err: *mut nftnl_parse_err, 971 | ) -> c_int; 972 | 973 | pub fn nftnl_set_elem_parse_file( 974 | e: *mut nftnl_set_elem, 975 | type_: nftnl_parse_type, 976 | fp: *mut FILE, 977 | err: *mut nftnl_parse_err, 978 | ) -> c_int; 979 | 980 | pub fn nftnl_set_elem_snprintf( 981 | buf: *mut c_char, 982 | size: usize, 983 | s: *const nftnl_set_elem, 984 | type_: u32, 985 | flags: u32, 986 | ) -> c_int; 987 | 988 | pub fn nftnl_set_elem_fprintf( 989 | fp: *mut FILE, 990 | se: *mut nftnl_set_elem, 991 | type_: u32, 992 | flags: u32, 993 | ) -> c_int; 994 | 995 | pub fn nftnl_set_elem_foreach( 996 | s: *mut nftnl_set, 997 | cb: Option c_int>, 998 | data: *mut c_void, 999 | ) -> c_int; 1000 | } 1001 | #[repr(C)] 1002 | pub struct nftnl_set_elems_iter(c_void); 1003 | 1004 | extern "C" { 1005 | pub fn nftnl_set_elems_iter_create(s: *const nftnl_set) -> *mut nftnl_set_elems_iter; 1006 | 1007 | pub fn nftnl_set_elems_iter_cur(iter: *const nftnl_set_elems_iter) -> *mut nftnl_set_elem; 1008 | 1009 | pub fn nftnl_set_elems_iter_next(iter: *mut nftnl_set_elems_iter) -> *mut nftnl_set_elem; 1010 | 1011 | pub fn nftnl_set_elems_iter_destroy(iter: *mut nftnl_set_elems_iter); 1012 | 1013 | pub fn nftnl_set_elems_nlmsg_build_payload_iter( 1014 | nlh: *mut nlmsghdr, 1015 | iter: *mut nftnl_set_elems_iter, 1016 | ) -> c_int; 1017 | } 1018 | #[repr(C)] 1019 | pub struct nftnl_table(c_void); 1020 | 1021 | extern "C" { 1022 | pub fn nftnl_table_alloc() -> *mut nftnl_table; 1023 | 1024 | pub fn nftnl_table_free(arg1: *const nftnl_table); 1025 | } 1026 | pub const NFTNL_TABLE_NAME: nftnl_table_attr = 0; 1027 | pub const NFTNL_TABLE_FAMILY: nftnl_table_attr = 1; 1028 | pub const NFTNL_TABLE_FLAGS: nftnl_table_attr = 2; 1029 | pub const NFTNL_TABLE_USE: nftnl_table_attr = 3; 1030 | pub const __NFTNL_TABLE_MAX: nftnl_table_attr = 4; 1031 | pub type nftnl_table_attr = u32; 1032 | extern "C" { 1033 | pub fn nftnl_table_is_set(t: *const nftnl_table, attr: u16) -> bool; 1034 | 1035 | pub fn nftnl_table_unset(t: *mut nftnl_table, attr: u16); 1036 | 1037 | pub fn nftnl_table_set(t: *mut nftnl_table, attr: u16, data: *const c_void); 1038 | 1039 | pub fn nftnl_table_set_data( 1040 | t: *mut nftnl_table, 1041 | attr: u16, 1042 | data: *const c_void, 1043 | data_len: u32, 1044 | ) -> c_int; 1045 | 1046 | pub fn nftnl_table_get(t: *const nftnl_table, attr: u16) -> *const c_void; 1047 | 1048 | pub fn nftnl_table_get_data( 1049 | t: *const nftnl_table, 1050 | attr: u16, 1051 | data_len: *mut u32, 1052 | ) -> *const c_void; 1053 | 1054 | pub fn nftnl_table_set_u8(t: *mut nftnl_table, attr: u16, data: u8); 1055 | 1056 | pub fn nftnl_table_set_u32(t: *mut nftnl_table, attr: u16, data: u32); 1057 | 1058 | pub fn nftnl_table_set_str(t: *mut nftnl_table, attr: u16, str: *const c_char) -> c_int; 1059 | 1060 | pub fn nftnl_table_get_u8(t: *const nftnl_table, attr: u16) -> u8; 1061 | 1062 | pub fn nftnl_table_get_u32(t: *const nftnl_table, attr: u16) -> u32; 1063 | 1064 | pub fn nftnl_table_get_str(t: *const nftnl_table, attr: u16) -> *const c_char; 1065 | 1066 | pub fn nftnl_table_nlmsg_build_payload(nlh: *mut nlmsghdr, t: *const nftnl_table); 1067 | 1068 | pub fn nftnl_table_parse( 1069 | t: *mut nftnl_table, 1070 | type_: nftnl_parse_type, 1071 | data: *const c_char, 1072 | err: *mut nftnl_parse_err, 1073 | ) -> c_int; 1074 | 1075 | pub fn nftnl_table_parse_file( 1076 | t: *mut nftnl_table, 1077 | type_: nftnl_parse_type, 1078 | fp: *mut FILE, 1079 | err: *mut nftnl_parse_err, 1080 | ) -> c_int; 1081 | 1082 | pub fn nftnl_table_snprintf( 1083 | buf: *mut c_char, 1084 | size: usize, 1085 | t: *const nftnl_table, 1086 | type_: u32, 1087 | flags: u32, 1088 | ) -> c_int; 1089 | 1090 | pub fn nftnl_table_fprintf( 1091 | fp: *mut FILE, 1092 | t: *const nftnl_table, 1093 | type_: u32, 1094 | flags: u32, 1095 | ) -> c_int; 1096 | 1097 | pub fn nftnl_table_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_table) -> c_int; 1098 | } 1099 | #[repr(C)] 1100 | pub struct nftnl_table_list(c_void); 1101 | 1102 | extern "C" { 1103 | pub fn nftnl_table_list_alloc() -> *mut nftnl_table_list; 1104 | 1105 | pub fn nftnl_table_list_free(list: *mut nftnl_table_list); 1106 | 1107 | pub fn nftnl_table_list_is_empty(list: *const nftnl_table_list) -> c_int; 1108 | 1109 | pub fn nftnl_table_list_foreach( 1110 | table_list: *mut nftnl_table_list, 1111 | cb: Option c_int>, 1112 | data: *mut c_void, 1113 | ) -> c_int; 1114 | 1115 | pub fn nftnl_table_list_add(r: *mut nftnl_table, list: *mut nftnl_table_list); 1116 | 1117 | pub fn nftnl_table_list_add_tail(r: *mut nftnl_table, list: *mut nftnl_table_list); 1118 | 1119 | pub fn nftnl_table_list_del(r: *mut nftnl_table); 1120 | } 1121 | #[repr(C)] 1122 | pub struct nftnl_table_list_iter(c_void); 1123 | 1124 | extern "C" { 1125 | pub fn nftnl_table_list_iter_create(l: *const nftnl_table_list) -> *mut nftnl_table_list_iter; 1126 | 1127 | pub fn nftnl_table_list_iter_next(iter: *mut nftnl_table_list_iter) -> *mut nftnl_table; 1128 | 1129 | pub fn nftnl_table_list_iter_destroy(iter: *const nftnl_table_list_iter); 1130 | } 1131 | pub const NFTNL_TRACE_CHAIN: nftnl_trace_attr = 0; 1132 | pub const NFTNL_TRACE_FAMILY: nftnl_trace_attr = 1; 1133 | pub const NFTNL_TRACE_ID: nftnl_trace_attr = 2; 1134 | pub const NFTNL_TRACE_IIF: nftnl_trace_attr = 3; 1135 | pub const NFTNL_TRACE_IIFTYPE: nftnl_trace_attr = 4; 1136 | pub const NFTNL_TRACE_JUMP_TARGET: nftnl_trace_attr = 5; 1137 | pub const NFTNL_TRACE_OIF: nftnl_trace_attr = 6; 1138 | pub const NFTNL_TRACE_OIFTYPE: nftnl_trace_attr = 7; 1139 | pub const NFTNL_TRACE_MARK: nftnl_trace_attr = 8; 1140 | pub const NFTNL_TRACE_LL_HEADER: nftnl_trace_attr = 9; 1141 | pub const NFTNL_TRACE_NETWORK_HEADER: nftnl_trace_attr = 10; 1142 | pub const NFTNL_TRACE_TRANSPORT_HEADER: nftnl_trace_attr = 11; 1143 | pub const NFTNL_TRACE_TABLE: nftnl_trace_attr = 12; 1144 | pub const NFTNL_TRACE_TYPE: nftnl_trace_attr = 13; 1145 | pub const NFTNL_TRACE_RULE_HANDLE: nftnl_trace_attr = 14; 1146 | pub const NFTNL_TRACE_VERDICT: nftnl_trace_attr = 15; 1147 | pub const NFTNL_TRACE_NFPROTO: nftnl_trace_attr = 16; 1148 | pub const NFTNL_TRACE_POLICY: nftnl_trace_attr = 17; 1149 | pub const __NFTNL_TRACE_MAX: nftnl_trace_attr = 18; 1150 | pub type nftnl_trace_attr = u32; 1151 | #[repr(C)] 1152 | pub struct nftnl_trace(c_void); 1153 | 1154 | extern "C" { 1155 | pub fn nftnl_trace_alloc() -> *mut nftnl_trace; 1156 | 1157 | pub fn nftnl_trace_free(trace: *const nftnl_trace); 1158 | 1159 | pub fn nftnl_trace_is_set(trace: *const nftnl_trace, type_: u16) -> bool; 1160 | 1161 | pub fn nftnl_trace_get_data( 1162 | trace: *const nftnl_trace, 1163 | type_: u16, 1164 | data_len: *mut u32, 1165 | ) -> *const c_void; 1166 | 1167 | pub fn nftnl_trace_get_u16(trace: *const nftnl_trace, type_: u16) -> u16; 1168 | 1169 | pub fn nftnl_trace_get_u32(trace: *const nftnl_trace, type_: u16) -> u32; 1170 | 1171 | pub fn nftnl_trace_get_u64(trace: *const nftnl_trace, type_: u16) -> u64; 1172 | 1173 | pub fn nftnl_trace_get_str(trace: *const nftnl_trace, type_: u16) -> *const c_char; 1174 | 1175 | pub fn nftnl_trace_nlmsg_parse(nlh: *const nlmsghdr, t: *mut nftnl_trace) -> c_int; 1176 | } 1177 | #[repr(C)] 1178 | pub struct nftnl_udata(c_void); 1179 | 1180 | #[repr(C)] 1181 | pub struct nftnl_udata_buf(c_void); 1182 | 1183 | extern "C" { 1184 | pub fn nftnl_udata_buf_alloc(data_size: u32) -> *mut nftnl_udata_buf; 1185 | 1186 | pub fn nftnl_udata_buf_free(buf: *const nftnl_udata_buf); 1187 | 1188 | pub fn nftnl_udata_buf_len(buf: *const nftnl_udata_buf) -> u32; 1189 | 1190 | pub fn nftnl_udata_buf_data(buf: *const nftnl_udata_buf) -> *mut c_void; 1191 | 1192 | pub fn nftnl_udata_buf_put(buf: *mut nftnl_udata_buf, data: *const c_void, len: u32); 1193 | 1194 | pub fn nftnl_udata_start(buf: *const nftnl_udata_buf) -> *mut nftnl_udata; 1195 | 1196 | pub fn nftnl_udata_end(buf: *const nftnl_udata_buf) -> *mut nftnl_udata; 1197 | 1198 | pub fn nftnl_udata_put( 1199 | buf: *mut nftnl_udata_buf, 1200 | type_: u8, 1201 | len: u32, 1202 | value: *const c_void, 1203 | ) -> bool; 1204 | 1205 | pub fn nftnl_udata_put_strz(buf: *mut nftnl_udata_buf, type_: u8, strz: *const c_char) -> bool; 1206 | 1207 | pub fn nftnl_udata_type(attr: *const nftnl_udata) -> u8; 1208 | 1209 | pub fn nftnl_udata_len(attr: *const nftnl_udata) -> u8; 1210 | 1211 | pub fn nftnl_udata_get(attr: *const nftnl_udata) -> *mut c_void; 1212 | 1213 | pub fn nftnl_udata_next(attr: *const nftnl_udata) -> *mut nftnl_udata; 1214 | } 1215 | pub type nftnl_udata_cb_t = 1216 | Option c_int>; 1217 | extern "C" { 1218 | pub fn nftnl_udata_parse( 1219 | data: *const c_void, 1220 | data_len: u32, 1221 | cb: nftnl_udata_cb_t, 1222 | cb_data: *mut c_void, 1223 | ) -> c_int; 1224 | } 1225 | -------------------------------------------------------------------------------- /nftnl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nftnl" 3 | version = "0.7.0" 4 | authors = ["Mullvad VPN"] 5 | license = "MIT OR Apache-2.0" 6 | description = "Safe abstraction for libnftnl. Provides low-level userspace access to the in-kernel nf_tables subsystem" 7 | repository = "https://github.com/mullvad/nftnl-rs" 8 | readme = "../README.md" 9 | keywords = ["nftables", "nft", "firewall", "iptables", "netfilter"] 10 | categories = ["network-programming", "os::unix-apis", "api-bindings"] 11 | edition = "2021" 12 | rust-version = "1.63.0" 13 | 14 | [features] 15 | nftnl-1-0-7 = ["nftnl-sys/nftnl-1-0-7"] 16 | nftnl-1-0-8 = ["nftnl-sys/nftnl-1-0-8"] 17 | nftnl-1-0-9 = ["nftnl-sys/nftnl-1-0-9"] 18 | nftnl-1-1-0 = ["nftnl-sys/nftnl-1-1-0"] 19 | nftnl-1-1-1 = ["nftnl-sys/nftnl-1-1-1"] 20 | nftnl-1-1-2 = ["nftnl-sys/nftnl-1-1-2"] 21 | 22 | [dependencies] 23 | bitflags = "2.6.0" 24 | log = "0.4" 25 | nftnl-sys = { path = "../nftnl-sys", version = "0.6.2" } 26 | 27 | [dev-dependencies] 28 | ipnetwork = "0.20.0" 29 | mnl = "0.2.2" 30 | -------------------------------------------------------------------------------- /nftnl/examples/add-ingress-rule.rs: -------------------------------------------------------------------------------- 1 | //! Adds a table, an ingress chain and some rules to netfilter. 2 | //! 3 | //! This example uses `verdict accept` everywhere. So even after running this the firewall won't 4 | //! block anything. This is so anyone trying to run this does not end up in a strange state 5 | //! where they don't understand why their network is broken. Try changing to `verdict drop` if 6 | //! you want to see the block working. 7 | //! 8 | //! Run the following to print out current active tables, chains and rules in netfilter. Must be 9 | //! executed as root: 10 | //! ```bash 11 | //! # nft list ruleset 12 | //! ``` 13 | //! After running this example, the output should be the following: 14 | //! ```ignore 15 | //! table inet example-table { 16 | //! chain chain-for-ingress { 17 | //! type filter hook ingress priority -450; policy accept; 18 | //! ip saddr 127.0.0.1 counter packets 0 bytes 0 accept 19 | //! } 20 | //! } 21 | //! ``` 22 | //! 23 | //! Try pinging any IP in the network range denoted by the outgoing rule and see the counter 24 | //! increment: 25 | //! ```bash 26 | //! $ ping 127.0.0.2 27 | //! ``` 28 | //! 29 | //! Everything created by this example can be removed by running 30 | //! ```bash 31 | //! # nft delete table inet example-table 32 | //! ``` 33 | 34 | use nftnl::{ 35 | nft_expr, nftnl_sys::libc, Batch, Chain, ChainType, FinalizedBatch, Policy, ProtoFamily, Rule, 36 | Table, 37 | }; 38 | use std::{ffi::CString, io, net::Ipv4Addr}; 39 | 40 | const TABLE_NAME: &str = "example-table"; 41 | const CHAIN_NAME: &str = "chain-for-ingress"; 42 | 43 | fn main() -> Result<(), Box> { 44 | // Create a batch. This is used to store all the netlink messages we will later send. 45 | // Creating a new batch also automatically writes the initial batch begin message needed 46 | // to tell netlink this is a single transaction that might arrive over multiple netlink packets. 47 | let mut batch = Batch::new(); 48 | 49 | // Create a netfilter table operating on both IPv4 and IPv6 (ProtoFamily::Inet) 50 | let table = Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet); 51 | // Add the table to the batch with the `MsgType::Add` type, thus instructing netfilter to add 52 | // this table under its `ProtoFamily::Inet` ruleset. 53 | batch.add(&table, nftnl::MsgType::Add); 54 | 55 | // Create input and output chains under the table we created above. 56 | let mut chain = Chain::new(&CString::new(CHAIN_NAME).unwrap(), &table); 57 | 58 | // Hook the chain to the input and output event hooks, with highest priority (priority zero). 59 | // See the `Chain::set_hook` documentation for details. 60 | chain.set_hook(nftnl::Hook::Ingress, -450); // -450 priority places this chain before any conntrack or defragmentation 61 | 62 | // Setting the chain type to filter is not necessary, as it is the default type. 63 | chain.set_type(ChainType::Filter); 64 | 65 | // Ingress hooks need a device to bind to. 66 | chain.set_device(&CString::new("lo").unwrap()); 67 | 68 | // Set the default policies on the chains. If no rule matches a packet processed by the 69 | // `out_chain` or the `in_chain` it will accept the packet. 70 | chain.set_policy(Policy::Accept); 71 | 72 | // Add the two chains to the batch with the `MsgType` to tell netfilter to create the chains 73 | // under the table. 74 | batch.add(&chain, nftnl::MsgType::Add); 75 | 76 | // === ADD A RULE ALLOWING (AND COUNTING) ALL PACKETS FROM THE 127.0.0.1 IP ADDRESS === 77 | 78 | let mut rule = Rule::new(&chain); 79 | let local_ip = Ipv4Addr::new(127, 0, 0, 1); 80 | 81 | // Load the `nfproto` metadata into the netfilter register. This metadata denotes which layer3 82 | // protocol the packet being processed is using. 83 | rule.add_expr(&nft_expr!(meta nfproto)); 84 | // Check if the currently processed packet is an IPv4 packet. This must be done before payload 85 | // data assuming the packet uses IPv4 can be loaded in the next expression. 86 | rule.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV4 as u8)); 87 | 88 | // Load the IPv4 destination address into the netfilter register. 89 | rule.add_expr(&nft_expr!(payload ipv4 saddr)); 90 | // Compare the register with the IP we are interested in. 91 | rule.add_expr(&nft_expr!(cmp == local_ip)); 92 | 93 | // Add a packet counter to the rule. Shows how many packets have been evaluated against this 94 | // expression. Since expressions are evaluated from first to last, putting this counter before 95 | // the above IP net check would make the counter increment on all packets also *not* matching 96 | // those expressions. Because the counter would then be evaluated before it fails a check. 97 | // Similarly, if the counter was added after the verdict it would always remain at zero. Since 98 | // when the packet hits the verdict expression any further processing of expressions stop. 99 | rule.add_expr(&nft_expr!(counter)); 100 | 101 | // Accept all the packets matching the rule so far. 102 | rule.add_expr(&nft_expr!(verdict accept)); 103 | 104 | // Add the rule to the batch. Without this nothing would be sent over netlink and netfilter, 105 | // and all the work on `block_out_to_private_net_rule` so far would go to waste. 106 | batch.add(&rule, nftnl::MsgType::Add); 107 | 108 | // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === 109 | 110 | // Finalize the batch. This means the batch end message is written into the batch, telling 111 | // netfilter that we reached the end of the transaction message. It's also converted to a type 112 | // that implements `IntoIterator`, thus allowing us to get the raw netlink data 113 | // out so it can be sent over a netlink socket to netfilter. 114 | let finalized_batch = batch.finalize(); 115 | 116 | // Send the entire batch and process any returned messages. 117 | send_and_process(&finalized_batch)?; 118 | Ok(()) 119 | } 120 | 121 | fn send_and_process(batch: &FinalizedBatch) -> io::Result<()> { 122 | // Create a netlink socket to netfilter. 123 | let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; 124 | // Send all the bytes in the batch. 125 | socket.send_all(batch)?; 126 | 127 | // Try to parse the messages coming back from netfilter. This part is still very unclear. 128 | let portid = socket.portid(); 129 | let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; 130 | let very_unclear_what_this_is_for = 2; 131 | while let Some(message) = socket_recv(&socket, &mut buffer[..])? { 132 | match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { 133 | mnl::CbResult::Stop => { 134 | break; 135 | } 136 | mnl::CbResult::Ok => (), 137 | } 138 | } 139 | Ok(()) 140 | } 141 | 142 | fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> io::Result> { 143 | let ret = socket.recv(buf)?; 144 | if ret > 0 { 145 | Ok(Some(&buf[..ret])) 146 | } else { 147 | Ok(None) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /nftnl/examples/add-rules.rs: -------------------------------------------------------------------------------- 1 | //! Adds a table, two chains and some rules to netfilter. 2 | //! 3 | //! This example uses `verdict accept` everywhere. So even after running this the firewall won't 4 | //! block anything. This is so anyone trying to run this does not end up in a strange state 5 | //! where they don't understand why their network is broken. Try changing to `verdict drop` if 6 | //! you want to see the block working. 7 | //! 8 | //! Run the following to print out current active tables, chains and rules in netfilter. Must be 9 | //! executed as root: 10 | //! ```bash 11 | //! # nft list ruleset 12 | //! ``` 13 | //! After running this example, the output should be the following: 14 | //! ```ignore 15 | //! table inet example-table { 16 | //! chain chain-for-outgoing-packets { 17 | //! type filter hook output priority 0; policy accept; 18 | //! ip daddr 10.1.0.0/24 counter packets 0 bytes 0 accept 19 | //! } 20 | //! 21 | //! chain chain-for-incoming-packets { 22 | //! type filter hook input priority 0; policy accept; 23 | //! iif "lo" accept 24 | //! } 25 | //! } 26 | //! ``` 27 | //! 28 | //! Try pinging any IP in the network range denoted by the outgoing rule and see the counter 29 | //! increment: 30 | //! ```bash 31 | //! $ ping 10.1.0.7 32 | //! ``` 33 | //! 34 | //! Everything created by this example can be removed by running 35 | //! ```bash 36 | //! # nft delete table inet example-table 37 | //! ``` 38 | 39 | use ipnetwork::{IpNetwork, Ipv4Network}; 40 | use nftnl::{nft_expr, nftnl_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; 41 | use std::{ffi::CString, io, net::Ipv4Addr}; 42 | 43 | const TABLE_NAME: &str = "example-table"; 44 | const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; 45 | const IN_CHAIN_NAME: &str = "chain-for-incoming-packets"; 46 | 47 | fn main() -> Result<(), Box> { 48 | // Create a batch. This is used to store all the netlink messages we will later send. 49 | // Creating a new batch also automatically writes the initial batch begin message needed 50 | // to tell netlink this is a single transaction that might arrive over multiple netlink packets. 51 | let mut batch = Batch::new(); 52 | 53 | // Create a netfilter table operating on both IPv4 and IPv6 (ProtoFamily::Inet) 54 | let table = Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet); 55 | // Add the table to the batch with the `MsgType::Add` type, thus instructing netfilter to add 56 | // this table under its `ProtoFamily::Inet` ruleset. 57 | batch.add(&table, nftnl::MsgType::Add); 58 | 59 | // Create input and output chains under the table we created above. 60 | let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), &table); 61 | let mut in_chain = Chain::new(&CString::new(IN_CHAIN_NAME).unwrap(), &table); 62 | 63 | // Hook the chains to the input and output event hooks, with highest priority (priority zero). 64 | // See the `Chain::set_hook` documentation for details. 65 | out_chain.set_hook(nftnl::Hook::Out, 0); 66 | in_chain.set_hook(nftnl::Hook::In, 0); 67 | 68 | // Set the default policies on the chains. If no rule matches a packet processed by the 69 | // `out_chain` or the `in_chain` it will accept the packet. 70 | out_chain.set_policy(nftnl::Policy::Accept); 71 | in_chain.set_policy(nftnl::Policy::Accept); 72 | 73 | // Add the two chains to the batch with the `MsgType` to tell netfilter to create the chains 74 | // under the table. 75 | batch.add(&out_chain, nftnl::MsgType::Add); 76 | batch.add(&in_chain, nftnl::MsgType::Add); 77 | 78 | // === ADD RULE ALLOWING ALL TRAFFIC TO THE LOOPBACK DEVICE === 79 | 80 | // Create a new rule object under the input chain. 81 | let mut allow_loopback_in_rule = Rule::new(&in_chain); 82 | // Lookup the interface index of the loopback interface. 83 | let lo_iface_index = iface_index("lo")?; 84 | 85 | // First expression to be evaluated in this rule is load the meta information "iif" 86 | // (incoming interface index) into the comparison register of netfilter. 87 | // When an incoming network packet is processed by this rule it will first be processed by this 88 | // expression, which will load the interface index of the interface the packet came from into 89 | // a special "register" in netfilter. 90 | allow_loopback_in_rule.add_expr(&nft_expr!(meta iif)); 91 | // Next expression in the rule is to compare the value loaded into the register with our desired 92 | // interface index, and succeed only if it's equal. For any packet processed where the equality 93 | // does not hold the packet is said to not match this rule, and the packet moves on to be 94 | // processed by the next rule in the chain instead. 95 | allow_loopback_in_rule.add_expr(&nft_expr!(cmp == lo_iface_index)); 96 | 97 | // Add a verdict expression to the rule. Any packet getting this far in the expression 98 | // processing without failing any expression will be given the verdict added here. 99 | allow_loopback_in_rule.add_expr(&nft_expr!(verdict accept)); 100 | 101 | // Add the rule to the batch. 102 | batch.add(&allow_loopback_in_rule, nftnl::MsgType::Add); 103 | 104 | // === ADD A RULE ALLOWING (AND COUNTING) ALL PACKETS TO THE 10.1.0.0/24 NETWORK === 105 | 106 | let mut block_out_to_private_net_rule = Rule::new(&out_chain); 107 | let private_net_ip = Ipv4Addr::new(10, 1, 0, 0); 108 | let private_net_prefix = 24; 109 | let private_net = IpNetwork::V4(Ipv4Network::new(private_net_ip, private_net_prefix)?); 110 | 111 | // Load the `nfproto` metadata into the netfilter register. This metadata denotes which layer3 112 | // protocol the packet being processed is using. 113 | block_out_to_private_net_rule.add_expr(&nft_expr!(meta nfproto)); 114 | // Check if the currently processed packet is an IPv4 packet. This must be done before payload 115 | // data assuming the packet uses IPv4 can be loaded in the next expression. 116 | block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV4 as u8)); 117 | 118 | // Load the IPv4 destination address into the netfilter register. 119 | block_out_to_private_net_rule.add_expr(&nft_expr!(payload ipv4 daddr)); 120 | // Mask out the part of the destination address that is not part of the network bits. The result 121 | // of this bitwise masking is stored back into the same netfilter register. 122 | block_out_to_private_net_rule.add_expr(&nft_expr!(bitwise mask private_net.mask(), xor 0)); 123 | // Compare the result of the masking with the IP of the network we are interested in. 124 | block_out_to_private_net_rule.add_expr(&nft_expr!(cmp == private_net.ip())); 125 | 126 | // Add a packet counter to the rule. Shows how many packets have been evaluated against this 127 | // expression. Since expressions are evaluated from first to last, putting this counter before 128 | // the above IP net check would make the counter increment on all packets also *not* matching 129 | // those expressions. Because the counter would then be evaluated before it fails a check. 130 | // Similarly, if the counter was added after the verdict it would always remain at zero. Since 131 | // when the packet hits the verdict expression any further processing of expressions stop. 132 | block_out_to_private_net_rule.add_expr(&nft_expr!(counter)); 133 | 134 | // Accept all the packets matching the rule so far. 135 | block_out_to_private_net_rule.add_expr(&nft_expr!(verdict accept)); 136 | 137 | // Add the rule to the batch. Without this nothing would be sent over netlink and netfilter, 138 | // and all the work on `block_out_to_private_net_rule` so far would go to waste. 139 | batch.add(&block_out_to_private_net_rule, nftnl::MsgType::Add); 140 | 141 | // === ADD A RULE ALLOWING ALL OUTGOING ICMPv6 PACKETS WITH TYPE 133 AND CODE 0 === 142 | 143 | let mut allow_router_solicitation = Rule::new(&out_chain); 144 | 145 | // Check that the packet is IPv6 and ICMPv6 146 | allow_router_solicitation.add_expr(&nft_expr!(meta nfproto)); 147 | allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::NFPROTO_IPV6 as u8)); 148 | allow_router_solicitation.add_expr(&nft_expr!(meta l4proto)); 149 | allow_router_solicitation.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8)); 150 | 151 | allow_router_solicitation.add_expr(&nftnl::expr::Payload::Transport( 152 | nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type), 153 | )); 154 | allow_router_solicitation.add_expr(&nft_expr!(cmp == 133u8)); 155 | allow_router_solicitation.add_expr(&nftnl::expr::Payload::Transport( 156 | nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code), 157 | )); 158 | allow_router_solicitation.add_expr(&nft_expr!(cmp == 0u8)); 159 | 160 | allow_router_solicitation.add_expr(&nft_expr!(verdict accept)); 161 | 162 | batch.add(&allow_router_solicitation, nftnl::MsgType::Add); 163 | 164 | // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === 165 | 166 | // Finalize the batch. This means the batch end message is written into the batch, telling 167 | // netfilter the we reached the end of the transaction message. It's also converted to a type 168 | // that implements `IntoIterator`, thus allowing us to get the raw netlink data 169 | // out so it can be sent over a netlink socket to netfilter. 170 | let finalized_batch = batch.finalize(); 171 | 172 | // Send the entire batch and process any returned messages. 173 | send_and_process(&finalized_batch)?; 174 | Ok(()) 175 | } 176 | 177 | // Look up the interface index for a given interface name. 178 | fn iface_index(name: &str) -> io::Result { 179 | let c_name = CString::new(name).unwrap(); 180 | let index = unsafe { libc::if_nametoindex(c_name.as_ptr()) }; 181 | if index == 0 { 182 | Err(io::Error::last_os_error()) 183 | } else { 184 | Ok(index) 185 | } 186 | } 187 | 188 | fn send_and_process(batch: &FinalizedBatch) -> io::Result<()> { 189 | // Create a netlink socket to netfilter. 190 | let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; 191 | // Send all the bytes in the batch. 192 | socket.send_all(batch)?; 193 | 194 | // Try to parse the messages coming back from netfilter. This part is still very unclear. 195 | let portid = socket.portid(); 196 | let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; 197 | let very_unclear_what_this_is_for = 2; 198 | while let Some(message) = socket_recv(&socket, &mut buffer[..])? { 199 | match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { 200 | mnl::CbResult::Stop => { 201 | break; 202 | } 203 | mnl::CbResult::Ok => (), 204 | } 205 | } 206 | Ok(()) 207 | } 208 | 209 | fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> io::Result> { 210 | let ret = socket.recv(buf)?; 211 | if ret > 0 { 212 | Ok(Some(&buf[..ret])) 213 | } else { 214 | Ok(None) 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /nftnl/examples/filter-ethernet.rs: -------------------------------------------------------------------------------- 1 | //! Adds a table, chain and a rule that blocks all traffic to a given MAC address 2 | //! 3 | //! Run the following to print out current active tables, chains and rules in netfilter. Must be 4 | //! executed as root: 5 | //! ```bash 6 | //! # nft list ruleset 7 | //! ``` 8 | //! After running this example, the output should be the following: 9 | //! ```ignore 10 | //! table inet example-filter-ethernet { 11 | //! chain chain-for-outgoing-packets { 12 | //! type filter hook output priority 3; policy accept; 13 | //! ether daddr 00:00:00:00:00:00 drop 14 | //! counter packets 0 bytes 0 meta random > 2147483647 counter packets 0 bytes 0 15 | //! } 16 | //! } 17 | //! ``` 18 | //! 19 | //! 20 | //! Everything created by this example can be removed by running 21 | //! ```bash 22 | //! # nft delete table inet example-filter-ethernet 23 | //! ``` 24 | 25 | use nftnl::{nft_expr, nftnl_sys::libc, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table}; 26 | use std::{ffi::CString, io}; 27 | 28 | const TABLE_NAME: &str = "example-filter-ethernet"; 29 | const OUT_CHAIN_NAME: &str = "chain-for-outgoing-packets"; 30 | 31 | const BLOCK_THIS_MAC: &[u8] = &[0, 0, 0, 0, 0, 0]; 32 | 33 | fn main() -> io::Result<()> { 34 | // For verbose explanations of what all these lines up until the rule creation does, see the 35 | // `add-rules` example. 36 | let mut batch = Batch::new(); 37 | let table = Table::new(&CString::new(TABLE_NAME).unwrap(), ProtoFamily::Inet); 38 | batch.add(&table, nftnl::MsgType::Add); 39 | 40 | let mut out_chain = Chain::new(&CString::new(OUT_CHAIN_NAME).unwrap(), &table); 41 | out_chain.set_hook(nftnl::Hook::Out, 3); 42 | out_chain.set_policy(nftnl::Policy::Accept); 43 | batch.add(&out_chain, nftnl::MsgType::Add); 44 | 45 | // === ADD RULE DROPPING ALL TRAFFIC TO THE MAC ADDRESS IN `BLOCK_THIS_MAC` === 46 | 47 | let mut block_ethernet_rule = Rule::new(&out_chain); 48 | 49 | // Check that the interface type is an ethernet interface. Must be done before we can check 50 | // payload values in the ethernet header. 51 | block_ethernet_rule.add_expr(&nft_expr!(meta iiftype)); 52 | block_ethernet_rule.add_expr(&nft_expr!(cmp == libc::ARPHRD_ETHER)); 53 | 54 | // Compare the ethernet destination address against the MAC address we want to drop 55 | block_ethernet_rule.add_expr(&nft_expr!(payload ethernet daddr)); 56 | block_ethernet_rule.add_expr(&nft_expr!(cmp == BLOCK_THIS_MAC)); 57 | 58 | // Drop the matching packets. 59 | block_ethernet_rule.add_expr(&nft_expr!(verdict drop)); 60 | 61 | batch.add(&block_ethernet_rule, nftnl::MsgType::Add); 62 | 63 | // === FOR FUN, ADD A PACKET THAT MATCHES 50% OF ALL PACKETS === 64 | 65 | // This packet has a counter before and after the check that has 50% chance of matching. 66 | // So after a number of packets has passed through this rule, the first counter should have a 67 | // value approximately double that of the second counter. This rule has no verdict, so it never 68 | // does anything with the matching packets. 69 | let mut random_rule = Rule::new(&out_chain); 70 | // This counter expression will be evaluated (and increment the counter) for all packets coming 71 | // through. 72 | random_rule.add_expr(&nft_expr!(counter)); 73 | 74 | // Load a pseudo-random 32 bit unsigned integer into the netfilter register. 75 | random_rule.add_expr(&nft_expr!(meta random)); 76 | // Check if the random integer is larger than `u32::MAX/2`, thus having 50% chance of success. 77 | random_rule.add_expr(&nft_expr!(cmp > (u32::MAX / 2).to_be())); 78 | 79 | // Add a second counter. This will only be incremented for the packets passing the random check. 80 | random_rule.add_expr(&nft_expr!(counter)); 81 | 82 | batch.add(&random_rule, nftnl::MsgType::Add); 83 | 84 | // === FINALIZE THE TRANSACTION AND SEND THE DATA TO NETFILTER === 85 | 86 | let finalized_batch = batch.finalize(); 87 | send_and_process(&finalized_batch)?; 88 | Ok(()) 89 | } 90 | 91 | fn send_and_process(batch: &FinalizedBatch) -> io::Result<()> { 92 | // Create a netlink socket to netfilter. 93 | let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; 94 | // Send all the bytes in the batch. 95 | socket.send_all(batch)?; 96 | 97 | // Try to parse the messages coming back from netfilter. This part is still very unclear. 98 | let portid = socket.portid(); 99 | let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; 100 | let very_unclear_what_this_is_for = 2; 101 | while let Some(message) = socket_recv(&socket, &mut buffer[..])? { 102 | match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { 103 | mnl::CbResult::Stop => { 104 | break; 105 | } 106 | mnl::CbResult::Ok => (), 107 | } 108 | } 109 | Ok(()) 110 | } 111 | 112 | fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> io::Result> { 113 | let ret = socket.recv(buf)?; 114 | if ret > 0 { 115 | Ok(Some(&buf[..ret])) 116 | } else { 117 | Ok(None) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /nftnl/src/batch.rs: -------------------------------------------------------------------------------- 1 | use crate::{MsgType, NlMsg}; 2 | use core::fmt; 3 | use nftnl_sys::{self as sys, libc}; 4 | use std::ffi::c_void; 5 | use std::os::raw::c_char; 6 | use std::ptr; 7 | 8 | /// Error while communicating with netlink 9 | #[derive(Debug)] 10 | pub struct NetlinkError(()); 11 | 12 | impl fmt::Display for NetlinkError { 13 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 14 | "Error while communicating with netlink".fmt(f) 15 | } 16 | } 17 | 18 | impl std::error::Error for NetlinkError {} 19 | 20 | /// Check if the kernel supports batched netlink messages to netfilter. 21 | pub fn batch_is_supported() -> std::result::Result { 22 | match unsafe { sys::nftnl_batch_is_supported() } { 23 | 1 => Ok(true), 24 | 0 => Ok(false), 25 | _ => Err(NetlinkError(())), 26 | } 27 | } 28 | 29 | /// A batch of netfilter messages to be performed in one atomic operation. Corresponds to 30 | /// `nftnl_batch` in libnftnl. 31 | pub struct Batch { 32 | batch: *mut sys::nftnl_batch, 33 | seq: u32, 34 | } 35 | 36 | // Safety: It should be safe to pass this around and *read* from it 37 | // from multiple threads 38 | unsafe impl Send for Batch {} 39 | unsafe impl Sync for Batch {} 40 | 41 | impl Default for Batch { 42 | fn default() -> Self { 43 | Self::new() 44 | } 45 | } 46 | 47 | impl Batch { 48 | /// Creates a new nftnl batch with the [default page size]. 49 | /// 50 | /// [default page size]: fn.default_batch_page_size.html 51 | pub fn new() -> Self { 52 | Self::with_page_size(default_batch_page_size()) 53 | } 54 | 55 | /// Creates a new nftnl batch with the given batch size. 56 | pub fn with_page_size(batch_page_size: u32) -> Self { 57 | let batch = try_alloc!(unsafe { 58 | sys::nftnl_batch_alloc(batch_page_size, crate::nft_nlmsg_maxsize()) 59 | }); 60 | let mut this = Batch { batch, seq: 1 }; 61 | this.write_begin_msg(); 62 | this 63 | } 64 | 65 | /// Adds the given message to this batch. 66 | pub fn add(&mut self, msg: &T, msg_type: MsgType) { 67 | trace!("Writing NlMsg with seq {} to batch", self.seq); 68 | unsafe { msg.write(self.current(), self.seq, msg_type) }; 69 | self.next() 70 | } 71 | 72 | /// Adds all the messages in the given iterator to this batch. If any message fails to be added 73 | /// the error for that failure is returned and all messages up until that message stays added 74 | /// to the batch. 75 | pub fn add_iter(&mut self, msg_iter: I, msg_type: MsgType) 76 | where 77 | T: NlMsg, 78 | I: Iterator, 79 | { 80 | for msg in msg_iter { 81 | self.add(&msg, msg_type); 82 | } 83 | } 84 | 85 | /// Adds the final end message to the batch and returns a [`FinalizedBatch`] that can be used 86 | /// to send the messages to netfilter. 87 | /// 88 | /// [`FinalizedBatch`]: struct.FinalizedBatch.html 89 | pub fn finalize(mut self) -> FinalizedBatch { 90 | self.write_end_msg(); 91 | FinalizedBatch { batch: self } 92 | } 93 | 94 | fn current(&self) -> *mut c_void { 95 | unsafe { sys::nftnl_batch_buffer(self.batch) } 96 | } 97 | 98 | fn next(&mut self) { 99 | if unsafe { sys::nftnl_batch_update(self.batch) } < 0 { 100 | // See try_alloc definition. 101 | std::process::abort(); 102 | } 103 | self.seq += 1; 104 | } 105 | 106 | fn write_begin_msg(&mut self) { 107 | unsafe { sys::nftnl_batch_begin(self.current() as *mut c_char, self.seq) }; 108 | self.next(); 109 | } 110 | 111 | fn write_end_msg(&mut self) { 112 | unsafe { sys::nftnl_batch_end(self.current() as *mut c_char, self.seq) }; 113 | self.next(); 114 | } 115 | 116 | /// Returns the underlying `nftnl_batch` instance. 117 | pub fn as_raw_batch(&self) -> *mut sys::nftnl_batch { 118 | self.batch 119 | } 120 | } 121 | 122 | impl Drop for Batch { 123 | fn drop(&mut self) { 124 | unsafe { sys::nftnl_batch_free(self.batch) }; 125 | } 126 | } 127 | 128 | /// A wrapper over [`Batch`], guaranteed to start with a proper batch begin and end with a proper 129 | /// batch end message. Created from [`Batch::finalize`]. 130 | /// 131 | /// Can be turned into an iterator of the byte buffers to send to netlink to execute this batch. 132 | /// 133 | /// [`Batch`]: struct.Batch.html 134 | /// [`Batch::finalize`]: struct.Batch.html#method.finalize 135 | pub struct FinalizedBatch { 136 | batch: Batch, 137 | } 138 | 139 | impl FinalizedBatch { 140 | /// Returns the iterator over byte buffers to send to netlink. 141 | pub fn iter(&self) -> Iter<'_> { 142 | let num_pages = unsafe { sys::nftnl_batch_iovec_len(self.batch.as_raw_batch()) as usize }; 143 | let mut iovecs = vec![ 144 | libc::iovec { 145 | iov_base: ptr::null_mut(), 146 | iov_len: 0, 147 | }; 148 | num_pages 149 | ]; 150 | let iovecs_ptr = iovecs.as_mut_ptr(); 151 | unsafe { 152 | sys::nftnl_batch_iovec(self.batch.as_raw_batch(), iovecs_ptr, num_pages as u32); 153 | } 154 | Iter { 155 | iovecs: iovecs.into_iter(), 156 | _marker: ::std::marker::PhantomData, 157 | } 158 | } 159 | } 160 | 161 | impl<'a> IntoIterator for &'a FinalizedBatch { 162 | type Item = &'a [u8]; 163 | type IntoIter = Iter<'a>; 164 | 165 | fn into_iter(self) -> Iter<'a> { 166 | self.iter() 167 | } 168 | } 169 | 170 | pub struct Iter<'a> { 171 | iovecs: ::std::vec::IntoIter, 172 | _marker: ::std::marker::PhantomData<&'a ()>, 173 | } 174 | 175 | // Safety: It should be safe to pass this around and *read* from it 176 | // from multiple threads. 177 | unsafe impl Send for Iter<'_> {} 178 | unsafe impl Sync for Iter<'_> {} 179 | 180 | impl<'a> Iterator for Iter<'a> { 181 | type Item = &'a [u8]; 182 | 183 | fn next(&mut self) -> Option<&'a [u8]> { 184 | self.iovecs.next().map(|iovec| unsafe { 185 | ::std::slice::from_raw_parts(iovec.iov_base as *const u8, iovec.iov_len) 186 | }) 187 | } 188 | } 189 | 190 | /// selected batch page is 256 Kbytes long to load ruleset of 191 | /// half a million rules without hitting -EMSGSIZE due to large 192 | /// iovec. 193 | pub fn default_batch_page_size() -> u32 { 194 | unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u32 * 32 } 195 | } 196 | -------------------------------------------------------------------------------- /nftnl/src/chain.rs: -------------------------------------------------------------------------------- 1 | use crate::{MsgType, Table}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::{ 4 | ffi::{c_void, CStr}, 5 | fmt, 6 | os::raw::c_char, 7 | }; 8 | 9 | pub type Priority = i32; 10 | 11 | /// The netfilter event hooks a chain can register for. 12 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 13 | #[repr(u16)] 14 | pub enum Hook { 15 | /// Hook into the pre-routing stage of netfilter. Corresponds to `NF_INET_PRE_ROUTING`. 16 | PreRouting = libc::NF_INET_PRE_ROUTING as u16, 17 | /// Hook into the input stage of netfilter. Corresponds to `NF_INET_LOCAL_IN`. 18 | In = libc::NF_INET_LOCAL_IN as u16, 19 | /// Hook into the forward stage of netfilter. Corresponds to `NF_INET_FORWARD`. 20 | Forward = libc::NF_INET_FORWARD as u16, 21 | /// Hook into the output stage of netfilter. Corresponds to `NF_INET_LOCAL_OUT`. 22 | Out = libc::NF_INET_LOCAL_OUT as u16, 23 | /// Hook into the post-routing stage of netfilter. Corresponds to `NF_INET_POST_ROUTING`. 24 | PostRouting = libc::NF_INET_POST_ROUTING as u16, 25 | /// Hook into the ingress stage of netfilter. Corresponds to `NF_INET_INGRESS`. 26 | Ingress = libc::NF_INET_INGRESS as u16, 27 | } 28 | 29 | /// A chain policy. Decides what to do with a packet that was processed by the chain but did not 30 | /// match any rules. 31 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 32 | #[repr(u32)] 33 | pub enum Policy { 34 | /// Accept the packet. 35 | Accept = libc::NF_ACCEPT as u32, 36 | /// Drop the packet. 37 | Drop = libc::NF_DROP as u32, 38 | } 39 | 40 | /// Base chain type. 41 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 42 | pub enum ChainType { 43 | /// Used to filter packets. 44 | /// Supported protocols: ip, ip6, inet, arp, and bridge tables. 45 | Filter, 46 | /// Used to reroute packets if IP headers or packet marks are modified. 47 | /// Supported protocols: ip, and ip6 tables. 48 | Route, 49 | /// Used to perform NAT. 50 | /// Supported protocols: ip, and ip6 tables. 51 | Nat, 52 | } 53 | 54 | impl ChainType { 55 | fn as_c_str(&self) -> &'static [u8] { 56 | match *self { 57 | ChainType::Filter => b"filter\0", 58 | ChainType::Route => b"route\0", 59 | ChainType::Nat => b"nat\0", 60 | } 61 | } 62 | } 63 | 64 | /// Abstraction of a `nftnl_chain`. Chains reside inside [`Table`]s and they hold [`Rule`]s. 65 | /// 66 | /// There are two types of chains, "base chain" and "regular chain". See [`set_hook`] for more 67 | /// details. 68 | /// 69 | /// [`Table`]: struct.Table.html 70 | /// [`Rule`]: struct.Rule.html 71 | /// [`set_hook`]: #method.set_hook 72 | pub struct Chain<'a> { 73 | chain: *mut sys::nftnl_chain, 74 | table: &'a Table, 75 | } 76 | 77 | // Safety: It should be safe to pass this around and *read* from it 78 | // from multiple threads 79 | unsafe impl Send for Chain<'_> {} 80 | unsafe impl Sync for Chain<'_> {} 81 | 82 | impl<'a> Chain<'a> { 83 | /// Creates a new chain instance inside the given [`Table`] and with the given name. 84 | /// 85 | /// [`Table`]: struct.Table.html 86 | pub fn new>(name: &T, table: &'a Table) -> Chain<'a> { 87 | unsafe { 88 | let chain = try_alloc!(sys::nftnl_chain_alloc()); 89 | sys::nftnl_chain_set_u32( 90 | chain, 91 | sys::NFTNL_CHAIN_FAMILY as u16, 92 | table.get_family() as u32, 93 | ); 94 | sys::nftnl_chain_set_str( 95 | chain, 96 | sys::NFTNL_CHAIN_TABLE as u16, 97 | table.get_name().as_ptr(), 98 | ); 99 | sys::nftnl_chain_set_str(chain, sys::NFTNL_CHAIN_NAME as u16, name.as_ref().as_ptr()); 100 | Chain { chain, table } 101 | } 102 | } 103 | 104 | /// Sets the hook and priority for this chain. Without calling this method the chain well 105 | /// become a "regular chain" without any hook and will thus not receive any traffic unless 106 | /// some rule forward packets to it via goto or jump verdicts. 107 | /// 108 | /// By calling `set_hook` with a hook the chain that is created will be registered with that 109 | /// hook and is thus a "base chain". A "base chain" is an entry point for packets from the 110 | /// networking stack. 111 | pub fn set_hook(&mut self, hook: Hook, priority: Priority) { 112 | unsafe { 113 | sys::nftnl_chain_set_u32(self.chain, sys::NFTNL_CHAIN_HOOKNUM as u16, hook as u32); 114 | sys::nftnl_chain_set_s32(self.chain, sys::NFTNL_CHAIN_PRIO as u16, priority); 115 | } 116 | } 117 | 118 | /// Set the type of a base chain. This only applies if the chain has been registered 119 | /// with a hook by calling `set_hook`. 120 | pub fn set_type(&mut self, chain_type: ChainType) { 121 | unsafe { 122 | sys::nftnl_chain_set_str( 123 | self.chain, 124 | sys::NFTNL_CHAIN_TYPE as u16, 125 | chain_type.as_c_str().as_ptr() as *const c_char, 126 | ); 127 | } 128 | } 129 | 130 | /// Sets the default policy for this chain. That means what action netfilter will apply to 131 | /// packets processed by this chain, but that did not match any rules in it. 132 | pub fn set_policy(&mut self, policy: Policy) { 133 | unsafe { 134 | sys::nftnl_chain_set_u32(self.chain, sys::NFTNL_CHAIN_POLICY as u16, policy as u32); 135 | } 136 | } 137 | 138 | /// Sets the device for this chain. This only applies if the chain has been registered with an `ingress` hook by calling `set_hook`. 139 | pub fn set_device>(&mut self, device: &T) { 140 | unsafe { 141 | sys::nftnl_chain_set_str( 142 | self.chain, 143 | sys::NFTNL_CHAIN_DEV as u16, 144 | device.as_ref().as_ptr(), 145 | ); 146 | } 147 | } 148 | 149 | /// Returns the name of this chain. 150 | pub fn get_name(&self) -> &CStr { 151 | unsafe { 152 | let ptr = sys::nftnl_chain_get_str(self.chain, sys::NFTNL_CHAIN_NAME as u16); 153 | CStr::from_ptr(ptr) 154 | } 155 | } 156 | 157 | /// Returns a reference to the [`Table`] this chain belongs to 158 | /// 159 | /// [`Table`]: struct.Table.html 160 | pub fn get_table(&self) -> &Table { 161 | self.table 162 | } 163 | } 164 | 165 | impl fmt::Debug for Chain<'_> { 166 | /// Return a string representation of the chain. 167 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 168 | let mut buffer: [u8; 4096] = [0; 4096]; 169 | unsafe { 170 | sys::nftnl_chain_snprintf( 171 | buffer.as_mut_ptr() as *mut c_char, 172 | buffer.len(), 173 | self.chain, 174 | sys::NFTNL_OUTPUT_DEFAULT, 175 | 0, 176 | ); 177 | } 178 | let s = unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }; 179 | write!(fmt, "{:?}", s) 180 | } 181 | } 182 | 183 | unsafe impl crate::NlMsg for Chain<'_> { 184 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType) { 185 | let raw_msg_type = match msg_type { 186 | MsgType::Add => libc::NFT_MSG_NEWCHAIN, 187 | MsgType::Del => libc::NFT_MSG_DELCHAIN, 188 | }; 189 | let flags: u16 = match msg_type { 190 | MsgType::Add => (libc::NLM_F_ACK | libc::NLM_F_CREATE) as u16, 191 | MsgType::Del => libc::NLM_F_ACK as u16, 192 | }; 193 | let header = sys::nftnl_nlmsg_build_hdr( 194 | buf as *mut c_char, 195 | raw_msg_type as u16, 196 | self.table.get_family() as u16, 197 | flags, 198 | seq, 199 | ); 200 | sys::nftnl_chain_nlmsg_build_payload(header, self.chain); 201 | } 202 | } 203 | 204 | impl Drop for Chain<'_> { 205 | fn drop(&mut self) { 206 | unsafe { sys::nftnl_chain_free(self.chain) }; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /nftnl/src/expr/bitwise.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use crate::expr::cmp::ToSlice; 3 | use nftnl_sys::{self as sys, libc}; 4 | use std::ffi::c_void; 5 | use std::os::raw::c_char; 6 | 7 | /// Expression for performing bitwise masking and XOR on the data in a register. 8 | pub struct Bitwise { 9 | mask: M, 10 | xor: X, 11 | } 12 | 13 | impl Bitwise { 14 | /// Returns a new `Bitwise` instance that first masks the value it's applied to with `mask` 15 | /// and then performs xor with the value in `xor`. 16 | pub fn new(mask: M, xor: X) -> Self { 17 | Self { mask, xor } 18 | } 19 | } 20 | 21 | impl Expression for Bitwise { 22 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 23 | unsafe { 24 | let expr = try_alloc!(sys::nftnl_expr_alloc( 25 | b"bitwise\0" as *const _ as *const c_char 26 | )); 27 | 28 | let mask = self.mask.to_slice(); 29 | let xor = self.xor.to_slice(); 30 | assert!(mask.len() == xor.len()); 31 | let len = mask.len() as u32; 32 | 33 | sys::nftnl_expr_set_u32( 34 | expr, 35 | sys::NFTNL_EXPR_BITWISE_SREG as u16, 36 | libc::NFT_REG_1 as u32, 37 | ); 38 | sys::nftnl_expr_set_u32( 39 | expr, 40 | sys::NFTNL_EXPR_BITWISE_DREG as u16, 41 | libc::NFT_REG_1 as u32, 42 | ); 43 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_BITWISE_LEN as u16, len); 44 | 45 | sys::nftnl_expr_set( 46 | expr, 47 | sys::NFTNL_EXPR_BITWISE_MASK as u16, 48 | mask.as_ref() as *const _ as *const c_void, 49 | len, 50 | ); 51 | sys::nftnl_expr_set( 52 | expr, 53 | sys::NFTNL_EXPR_BITWISE_XOR as u16, 54 | xor.as_ref() as *const _ as *const c_void, 55 | len, 56 | ); 57 | 58 | expr 59 | } 60 | } 61 | } 62 | 63 | #[macro_export] 64 | macro_rules! nft_expr_bitwise { 65 | (mask $mask:expr,xor $xor:expr) => { 66 | $crate::expr::Bitwise::new($mask, $xor) 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /nftnl/src/expr/cmp.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::{ 4 | borrow::Cow, 5 | ffi::{c_void, CString}, 6 | net::{IpAddr, Ipv4Addr, Ipv6Addr}, 7 | os::raw::c_char, 8 | slice, 9 | }; 10 | 11 | /// Comparison operator. 12 | #[derive(Copy, Clone, Eq, PartialEq)] 13 | pub enum CmpOp { 14 | /// Equals. 15 | Eq, 16 | /// Not equal. 17 | Neq, 18 | /// Less than. 19 | Lt, 20 | /// Less than, or equal. 21 | Lte, 22 | /// Greater than. 23 | Gt, 24 | /// Greater than, or equal. 25 | Gte, 26 | } 27 | 28 | impl CmpOp { 29 | /// Returns the corresponding `NFT_*` constant for this comparison operation. 30 | pub fn to_raw(self) -> u32 { 31 | use self::CmpOp::*; 32 | match self { 33 | Eq => libc::NFT_CMP_EQ as u32, 34 | Neq => libc::NFT_CMP_NEQ as u32, 35 | Lt => libc::NFT_CMP_LT as u32, 36 | Lte => libc::NFT_CMP_LTE as u32, 37 | Gt => libc::NFT_CMP_GT as u32, 38 | Gte => libc::NFT_CMP_GTE as u32, 39 | } 40 | } 41 | } 42 | 43 | /// Comparator expression. Allows comparing the content of the netfilter register with any value. 44 | pub struct Cmp { 45 | op: CmpOp, 46 | data: T, 47 | } 48 | 49 | impl Cmp { 50 | /// Returns a new comparison expression comparing the value loaded in the register with the 51 | /// data in `data` using the comparison operator `op`. 52 | pub fn new(op: CmpOp, data: T) -> Self { 53 | Cmp { op, data } 54 | } 55 | } 56 | 57 | impl Expression for Cmp { 58 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 59 | unsafe { 60 | let expr = try_alloc!(sys::nftnl_expr_alloc(b"cmp\0" as *const _ as *const c_char)); 61 | 62 | let data = self.data.to_slice(); 63 | trace!("Creating a cmp expr comparing with data {:?}", data); 64 | 65 | sys::nftnl_expr_set_u32( 66 | expr, 67 | sys::NFTNL_EXPR_CMP_SREG as u16, 68 | libc::NFT_REG_1 as u32, 69 | ); 70 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_CMP_OP as u16, self.op.to_raw()); 71 | sys::nftnl_expr_set( 72 | expr, 73 | sys::NFTNL_EXPR_CMP_DATA as u16, 74 | data.as_ref() as *const _ as *const c_void, 75 | data.len() as u32, 76 | ); 77 | 78 | expr 79 | } 80 | } 81 | } 82 | 83 | #[macro_export(local_inner_macros)] 84 | macro_rules! nft_expr_cmp { 85 | (@cmp_op ==) => { 86 | $crate::expr::CmpOp::Eq 87 | }; 88 | (@cmp_op !=) => { 89 | $crate::expr::CmpOp::Neq 90 | }; 91 | (@cmp_op <) => { 92 | $crate::expr::CmpOp::Lt 93 | }; 94 | (@cmp_op <=) => { 95 | $crate::expr::CmpOp::Lte 96 | }; 97 | (@cmp_op >) => { 98 | $crate::expr::CmpOp::Gt 99 | }; 100 | (@cmp_op >=) => { 101 | $crate::expr::CmpOp::Gte 102 | }; 103 | ($op:tt $data:expr) => { 104 | $crate::expr::Cmp::new(nft_expr_cmp!(@cmp_op $op), $data) 105 | }; 106 | } 107 | 108 | /// A type that can be converted into a byte buffer. 109 | pub trait ToSlice { 110 | /// Returns the data this type represents. 111 | fn to_slice(&self) -> Cow<'_, [u8]>; 112 | } 113 | 114 | impl ToSlice for [u8; 0] { 115 | fn to_slice(&self) -> Cow<'_, [u8]> { 116 | Cow::Borrowed(&[]) 117 | } 118 | } 119 | 120 | impl ToSlice for &'_ [u8] { 121 | fn to_slice(&self) -> Cow<'_, [u8]> { 122 | Cow::Borrowed(self) 123 | } 124 | } 125 | 126 | impl ToSlice for &'_ [u16] { 127 | fn to_slice(&self) -> Cow<'_, [u8]> { 128 | let ptr = self.as_ptr() as *const u8; 129 | let len = self.len() * 2; 130 | Cow::Borrowed(unsafe { slice::from_raw_parts(ptr, len) }) 131 | } 132 | } 133 | 134 | impl ToSlice for IpAddr { 135 | fn to_slice(&self) -> Cow<'_, [u8]> { 136 | match *self { 137 | IpAddr::V4(ref addr) => addr.to_slice(), 138 | IpAddr::V6(ref addr) => addr.to_slice(), 139 | } 140 | } 141 | } 142 | 143 | impl ToSlice for Ipv4Addr { 144 | fn to_slice(&self) -> Cow<'_, [u8]> { 145 | Cow::Owned(self.octets().to_vec()) 146 | } 147 | } 148 | 149 | impl ToSlice for Ipv6Addr { 150 | fn to_slice(&self) -> Cow<'_, [u8]> { 151 | Cow::Owned(self.octets().to_vec()) 152 | } 153 | } 154 | 155 | impl ToSlice for u8 { 156 | fn to_slice(&self) -> Cow<'_, [u8]> { 157 | Cow::Owned(vec![*self]) 158 | } 159 | } 160 | 161 | impl ToSlice for u16 { 162 | fn to_slice(&self) -> Cow<'_, [u8]> { 163 | let b0 = (*self & 0x00ff) as u8; 164 | let b1 = (*self >> 8) as u8; 165 | Cow::Owned(vec![b0, b1]) 166 | } 167 | } 168 | 169 | impl ToSlice for u32 { 170 | fn to_slice(&self) -> Cow<'_, [u8]> { 171 | let b0 = *self as u8; 172 | let b1 = (*self >> 8) as u8; 173 | let b2 = (*self >> 16) as u8; 174 | let b3 = (*self >> 24) as u8; 175 | Cow::Owned(vec![b0, b1, b2, b3]) 176 | } 177 | } 178 | 179 | impl ToSlice for i32 { 180 | fn to_slice(&self) -> Cow<'_, [u8]> { 181 | let b0 = *self as u8; 182 | let b1 = (*self >> 8) as u8; 183 | let b2 = (*self >> 16) as u8; 184 | let b3 = (*self >> 24) as u8; 185 | Cow::Owned(vec![b0, b1, b2, b3]) 186 | } 187 | } 188 | 189 | impl ToSlice for &'_ str { 190 | fn to_slice(&self) -> Cow<'_, [u8]> { 191 | Cow::from(self.as_bytes()) 192 | } 193 | } 194 | 195 | /// Can be used to compare the value loaded by [`Meta::IifName`] and [`Meta::OifName`]. Please 196 | /// note that it is faster to check interface index than name. 197 | /// 198 | /// [`Meta::IifName`]: enum.Meta.html#variant.IifName 199 | /// [`Meta::OifName`]: enum.Meta.html#variant.OifName 200 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 201 | pub enum InterfaceName { 202 | /// Interface name must be exactly the value of the `CString`. 203 | Exact(CString), 204 | /// Interface name must start with the value of the `CString`. 205 | /// 206 | /// `InterfaceName::StartingWith("eth")` will look like `eth*` when printed and match against 207 | /// `eth0`, `eth1`, ..., `eth99` and so on. 208 | StartingWith(CString), 209 | } 210 | 211 | impl ToSlice for InterfaceName { 212 | fn to_slice(&self) -> Cow<'_, [u8]> { 213 | let bytes = match *self { 214 | InterfaceName::Exact(ref name) => name.as_bytes_with_nul(), 215 | InterfaceName::StartingWith(ref name) => name.as_bytes(), 216 | }; 217 | Cow::from(bytes) 218 | } 219 | } 220 | 221 | impl ToSlice for &'_ InterfaceName { 222 | fn to_slice(&self) -> Cow<'_, [u8]> { 223 | let bytes = match *self { 224 | InterfaceName::Exact(ref name) => name.as_bytes_with_nul(), 225 | InterfaceName::StartingWith(ref name) => name.as_bytes(), 226 | }; 227 | Cow::from(bytes) 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /nftnl/src/expr/counter.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys as sys; 3 | use std::os::raw::c_char; 4 | 5 | /// A counter expression adds a counter to the rule that is incremented to count number of packets 6 | /// and number of bytes for all packets that has matched the rule. 7 | pub struct Counter; 8 | 9 | impl Expression for Counter { 10 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 11 | try_alloc!(unsafe { sys::nftnl_expr_alloc(b"counter\0" as *const _ as *const c_char) }) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nftnl/src/expr/ct.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::os::raw::c_char; 4 | 5 | bitflags::bitflags! { 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 7 | pub struct States: u32 { 8 | const INVALID = 1; 9 | const ESTABLISHED = 2; 10 | const RELATED = 4; 11 | const NEW = 8; 12 | const UNTRACKED = 64; 13 | } 14 | } 15 | 16 | bitflags::bitflags! { 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 18 | pub struct ConntrackStatus: u32 { 19 | const EXPECTED = 1; 20 | const SEEN_REPLY = 2; 21 | const ASSURED = 4; 22 | const CONFIRMED = 8; 23 | const SRC_NAT = 16; 24 | const DST_NAT = 32; 25 | const SEQ_ADJUST = 64; 26 | const SRC_NAT_DONE = 128; 27 | const DST_NAT_DONE = 256; 28 | const DYING = 512; 29 | const FIXED_TIMEOUT = 1024; 30 | const TEMPLATE = 2048; 31 | const UNTRACKED = 4096; 32 | const HELPER = 8192; 33 | const OFFLOAD = 16384; 34 | const HW_OFFLOAD = 32768; 35 | } 36 | } 37 | 38 | pub enum Conntrack { 39 | State, 40 | Status, 41 | Mark { set: bool }, 42 | } 43 | 44 | impl Conntrack { 45 | fn raw_key(&self) -> u32 { 46 | match *self { 47 | Conntrack::State => libc::NFT_CT_STATE as u32, 48 | Conntrack::Status => libc::NFT_CT_STATUS as u32, 49 | Conntrack::Mark { .. } => libc::NFT_CT_MARK as u32, 50 | } 51 | } 52 | } 53 | 54 | impl Expression for Conntrack { 55 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 56 | unsafe { 57 | let expr = try_alloc!(sys::nftnl_expr_alloc(b"ct\0" as *const _ as *const c_char)); 58 | 59 | if let Conntrack::Mark { set: true } = self { 60 | sys::nftnl_expr_set_u32( 61 | expr, 62 | sys::NFTNL_EXPR_CT_SREG as u16, 63 | libc::NFT_REG_1 as u32, 64 | ); 65 | } else { 66 | sys::nftnl_expr_set_u32( 67 | expr, 68 | sys::NFTNL_EXPR_CT_DREG as u16, 69 | libc::NFT_REG_1 as u32, 70 | ); 71 | } 72 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_CT_KEY as u16, self.raw_key()); 73 | 74 | expr 75 | } 76 | } 77 | } 78 | 79 | #[macro_export] 80 | macro_rules! nft_expr_ct { 81 | (state) => { 82 | $crate::expr::Conntrack::State 83 | }; 84 | (status) => { 85 | $crate::expr::Conntrack::Status 86 | }; 87 | (mark set) => { 88 | $crate::expr::Conntrack::Mark { set: true } 89 | }; 90 | (mark) => { 91 | $crate::expr::Conntrack::Mark { set: false } 92 | }; 93 | } 94 | -------------------------------------------------------------------------------- /nftnl/src/expr/immediate.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Register, Rule}; 2 | use nftnl_sys as sys; 3 | use std::ffi::c_void; 4 | use std::mem::size_of_val; 5 | use std::os::raw::c_char; 6 | 7 | /// An immediate expression. Used to set immediate data. 8 | /// Verdicts are handled separately by [Verdict](super::Verdict). 9 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 10 | pub struct Immediate { 11 | pub data: T, 12 | pub register: Register, 13 | } 14 | 15 | impl Immediate { 16 | pub fn new(data: T, register: Register) -> Self { 17 | Self { data, register } 18 | } 19 | } 20 | 21 | impl Expression for Immediate { 22 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 23 | unsafe { 24 | let expr = try_alloc!(sys::nftnl_expr_alloc( 25 | b"immediate\0" as *const _ as *const c_char 26 | )); 27 | 28 | sys::nftnl_expr_set_u32( 29 | expr, 30 | sys::NFTNL_EXPR_IMM_DREG as u16, 31 | self.register.to_raw(), 32 | ); 33 | 34 | sys::nftnl_expr_set( 35 | expr, 36 | sys::NFTNL_EXPR_IMM_DATA as u16, 37 | &self.data as *const _ as *const c_void, 38 | size_of_val(&self.data) as u32, 39 | ); 40 | 41 | expr 42 | } 43 | } 44 | } 45 | 46 | #[macro_export] 47 | macro_rules! nft_expr_immediate { 48 | (data $value:expr) => { 49 | $crate::expr::Immediate { 50 | data: $value, 51 | register: $crate::expr::Register::Reg1, 52 | } 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /nftnl/src/expr/lookup.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use crate::set::Set; 3 | use nftnl_sys::{self as sys, libc}; 4 | use std::ffi::CString; 5 | use std::os::raw::c_char; 6 | 7 | pub struct Lookup { 8 | set_name: CString, 9 | set_id: u32, 10 | } 11 | 12 | impl Lookup { 13 | pub fn new(set: &Set<'_, K>) -> Self { 14 | Lookup { 15 | set_name: set.get_name().to_owned(), 16 | set_id: set.get_id(), 17 | } 18 | } 19 | } 20 | 21 | impl Expression for Lookup { 22 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 23 | unsafe { 24 | let expr = try_alloc!(sys::nftnl_expr_alloc( 25 | b"lookup\0" as *const _ as *const c_char 26 | )); 27 | 28 | sys::nftnl_expr_set_u32( 29 | expr, 30 | sys::NFTNL_EXPR_LOOKUP_SREG as u16, 31 | libc::NFT_REG_1 as u32, 32 | ); 33 | sys::nftnl_expr_set_str( 34 | expr, 35 | sys::NFTNL_EXPR_LOOKUP_SET as u16, 36 | self.set_name.as_ptr() as *const _ as *const c_char, 37 | ); 38 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_LOOKUP_SET_ID as u16, self.set_id); 39 | 40 | // This code is left here since it's quite likely we need it again when we get further 41 | // if self.reverse { 42 | // sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_LOOKUP_FLAGS as u16, 43 | // libc::NFT_LOOKUP_F_INV as u32); 44 | // } 45 | 46 | expr 47 | } 48 | } 49 | } 50 | 51 | #[macro_export] 52 | macro_rules! nft_expr_lookup { 53 | ($set:expr) => { 54 | $crate::expr::Lookup::new($set) 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /nftnl/src/expr/masquerade.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys as sys; 3 | use std::os::raw::c_char; 4 | 5 | /// Sets the source IP to that of the output interface. 6 | pub struct Masquerade; 7 | 8 | impl Expression for Masquerade { 9 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 10 | try_alloc!(unsafe { sys::nftnl_expr_alloc(b"masq\0" as *const _ as *const c_char) }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /nftnl/src/expr/meta.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::os::raw::c_char; 4 | 5 | /// A meta expression refers to meta data associated with a packet. 6 | #[non_exhaustive] 7 | pub enum Meta { 8 | /// Packet ethertype protocol (skb->protocol), invalid in OUTPUT. 9 | Protocol, 10 | /// Packet mark. 11 | Mark { set: bool }, 12 | /// Packet input interface index (dev->ifindex). 13 | Iif, 14 | /// Packet output interface index (dev->ifindex). 15 | Oif, 16 | /// Packet input interface name (dev->name) 17 | IifName, 18 | /// Packet output interface name (dev->name). 19 | OifName, 20 | /// Packet input interface type (dev->type). 21 | IifType, 22 | /// Packet output interface type (dev->type). 23 | OifType, 24 | /// Originating socket UID (fsuid). 25 | SkUid, 26 | /// Originating socket GID (fsgid). 27 | SkGid, 28 | /// Netfilter protocol (Transport layer protocol). 29 | NfProto, 30 | /// Layer 4 protocol number. 31 | L4Proto, 32 | /// Socket control group (skb->sk->sk_classid). 33 | Cgroup, 34 | /// A 32bit pseudo-random number 35 | PRandom, 36 | } 37 | 38 | impl Meta { 39 | /// Returns the corresponding `NFT_*` constant for this meta expression. 40 | pub fn to_raw_key(&self) -> u32 { 41 | use Meta::*; 42 | match *self { 43 | Protocol => libc::NFT_META_PROTOCOL as u32, 44 | Mark { .. } => libc::NFT_META_MARK as u32, 45 | Iif => libc::NFT_META_IIF as u32, 46 | Oif => libc::NFT_META_OIF as u32, 47 | IifName => libc::NFT_META_IIFNAME as u32, 48 | OifName => libc::NFT_META_OIFNAME as u32, 49 | IifType => libc::NFT_META_IIFTYPE as u32, 50 | OifType => libc::NFT_META_OIFTYPE as u32, 51 | SkUid => libc::NFT_META_SKUID as u32, 52 | SkGid => libc::NFT_META_SKGID as u32, 53 | NfProto => libc::NFT_META_NFPROTO as u32, 54 | L4Proto => libc::NFT_META_L4PROTO as u32, 55 | Cgroup => libc::NFT_META_CGROUP as u32, 56 | PRandom => libc::NFT_META_PRANDOM as u32, 57 | } 58 | } 59 | } 60 | 61 | impl Expression for Meta { 62 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 63 | unsafe { 64 | let expr = try_alloc!(sys::nftnl_expr_alloc( 65 | b"meta\0" as *const _ as *const c_char 66 | )); 67 | 68 | if let Meta::Mark { set: true } = self { 69 | sys::nftnl_expr_set_u32( 70 | expr, 71 | sys::NFTNL_EXPR_META_SREG as u16, 72 | libc::NFT_REG_1 as u32, 73 | ); 74 | } else { 75 | sys::nftnl_expr_set_u32( 76 | expr, 77 | sys::NFTNL_EXPR_META_DREG as u16, 78 | libc::NFT_REG_1 as u32, 79 | ); 80 | } 81 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_META_KEY as u16, self.to_raw_key()); 82 | expr 83 | } 84 | } 85 | } 86 | 87 | #[macro_export] 88 | macro_rules! nft_expr_meta { 89 | (proto) => { 90 | $crate::expr::Meta::Protocol 91 | }; 92 | (mark set) => { 93 | $crate::expr::Meta::Mark { set: true } 94 | }; 95 | (mark) => { 96 | $crate::expr::Meta::Mark { set: false } 97 | }; 98 | (iif) => { 99 | $crate::expr::Meta::Iif 100 | }; 101 | (oif) => { 102 | $crate::expr::Meta::Oif 103 | }; 104 | (iifname) => { 105 | $crate::expr::Meta::IifName 106 | }; 107 | (oifname) => { 108 | $crate::expr::Meta::OifName 109 | }; 110 | (iiftype) => { 111 | $crate::expr::Meta::IifType 112 | }; 113 | (oiftype) => { 114 | $crate::expr::Meta::OifType 115 | }; 116 | (skuid) => { 117 | $crate::expr::Meta::SkUid 118 | }; 119 | (skgid) => { 120 | $crate::expr::Meta::SkGid 121 | }; 122 | (nfproto) => { 123 | $crate::expr::Meta::NfProto 124 | }; 125 | (l4proto) => { 126 | $crate::expr::Meta::L4Proto 127 | }; 128 | (cgroup) => { 129 | $crate::expr::Meta::Cgroup 130 | }; 131 | (random) => { 132 | $crate::expr::Meta::PRandom 133 | }; 134 | } 135 | -------------------------------------------------------------------------------- /nftnl/src/expr/mod.rs: -------------------------------------------------------------------------------- 1 | //! A module with all the nftables expressions that can be added to [`Rule`]s to build up how 2 | //! they match against packets. 3 | //! 4 | //! [`Rule`]: struct.Rule.html 5 | 6 | use super::rule::Rule; 7 | use nftnl_sys::{self as sys, libc}; 8 | 9 | /// Trait for every safe wrapper of an nftables expression. 10 | pub trait Expression { 11 | /// Allocates and returns the low level `nftnl_expr` representation of this expression. 12 | /// The caller to this method is responsible for freeing the expression. 13 | fn to_expr(&self, rule: &Rule) -> *mut sys::nftnl_expr; 14 | } 15 | 16 | /// A netfilter data register. The expressions store and read data to and from these 17 | /// when evaluating rule statements. 18 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 19 | #[repr(i32)] 20 | pub enum Register { 21 | Reg1 = libc::NFT_REG_1, 22 | Reg2 = libc::NFT_REG_2, 23 | Reg3 = libc::NFT_REG_3, 24 | Reg4 = libc::NFT_REG_4, 25 | } 26 | 27 | impl Register { 28 | pub fn to_raw(self) -> u32 { 29 | self as u32 30 | } 31 | } 32 | 33 | mod bitwise; 34 | pub use self::bitwise::*; 35 | 36 | mod cmp; 37 | pub use self::cmp::*; 38 | 39 | mod counter; 40 | pub use self::counter::*; 41 | 42 | pub mod ct; 43 | pub use self::ct::*; 44 | 45 | mod immediate; 46 | pub use self::immediate::*; 47 | 48 | mod lookup; 49 | pub use self::lookup::*; 50 | 51 | mod masquerade; 52 | pub use self::masquerade::*; 53 | 54 | mod meta; 55 | pub use self::meta::*; 56 | 57 | mod nat; 58 | pub use self::nat::*; 59 | 60 | mod payload; 61 | pub use self::payload::*; 62 | 63 | mod verdict; 64 | pub use self::verdict::*; 65 | 66 | #[macro_export(local_inner_macros)] 67 | macro_rules! nft_expr { 68 | (bitwise mask $mask:expr,xor $xor:expr) => { 69 | nft_expr_bitwise!(mask $mask, xor $xor) 70 | }; 71 | (cmp $op:tt $data:expr) => { 72 | nft_expr_cmp!($op $data) 73 | }; 74 | (counter) => { 75 | $crate::expr::Counter 76 | }; 77 | (ct $key:ident set) => { 78 | nft_expr_ct!($key set) 79 | }; 80 | (ct $key:ident) => { 81 | nft_expr_ct!($key) 82 | }; 83 | (verdict $verdict:ident) => { 84 | nft_expr_verdict!($verdict) 85 | }; 86 | (verdict $verdict:ident $chain:expr) => { 87 | nft_expr_verdict!($verdict $chain) 88 | }; 89 | (lookup $set:expr) => { 90 | nft_expr_lookup!($set) 91 | }; 92 | (masquerade) => { 93 | $crate::expr::Masquerade 94 | }; 95 | (meta $expr:ident set) => { 96 | nft_expr_meta!($expr set) 97 | }; 98 | (meta $expr:ident) => { 99 | nft_expr_meta!($expr) 100 | }; 101 | (payload $proto:ident $field:ident) => { 102 | nft_expr_payload!($proto $field) 103 | }; 104 | (payload_raw $base:ident $offset:expr, $length:expr) => { 105 | nft_expr_payload!($base $offset, $length) 106 | }; 107 | (immediate $expr:ident $value:expr) => { 108 | nft_expr_immediate!($expr $value) 109 | }; 110 | } 111 | -------------------------------------------------------------------------------- /nftnl/src/expr/nat.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Register, Rule}; 2 | use crate::ProtoFamily; 3 | use nftnl_sys::{self as sys, libc}; 4 | use std::os::raw::c_char; 5 | 6 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 7 | #[repr(i32)] 8 | pub enum NatType { 9 | /// Source NAT. Changes the source address of a packet 10 | SNat = libc::NFT_NAT_SNAT, 11 | /// Destination NAT. Changeth the destination address of a packet 12 | DNat = libc::NFT_NAT_DNAT, 13 | } 14 | 15 | /// A source or destination NAT statement. Modifies the source or destination address 16 | /// (and possibly port) of packets. 17 | pub struct Nat { 18 | pub nat_type: NatType, 19 | pub family: ProtoFamily, 20 | pub ip_register: Register, 21 | pub port_register: Option, 22 | } 23 | 24 | impl Expression for Nat { 25 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 26 | let expr = 27 | try_alloc!(unsafe { sys::nftnl_expr_alloc(b"nat\0" as *const _ as *const c_char) }); 28 | 29 | unsafe { 30 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_NAT_TYPE as u16, self.nat_type as u32); 31 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_NAT_FAMILY as u16, self.family as u32); 32 | sys::nftnl_expr_set_u32( 33 | expr, 34 | sys::NFTNL_EXPR_NAT_REG_ADDR_MIN as u16, 35 | self.ip_register.to_raw(), 36 | ); 37 | if let Some(port_register) = self.port_register { 38 | sys::nftnl_expr_set_u32( 39 | expr, 40 | sys::NFTNL_EXPR_NAT_REG_PROTO_MIN as u16, 41 | port_register.to_raw(), 42 | ); 43 | } 44 | } 45 | 46 | expr 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /nftnl/src/expr/payload.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::os::raw::c_char; 4 | 5 | trait HeaderField { 6 | fn offset(&self) -> u32; 7 | fn len(&self) -> u32; 8 | } 9 | 10 | /// Payload expressions refer to data from the packet's payload. 11 | #[derive(Copy, Clone, Eq, PartialEq)] 12 | pub enum Payload { 13 | LinkLayer(LLHeaderField), 14 | Network(NetworkHeaderField), 15 | Transport(TransportHeaderField), 16 | } 17 | 18 | impl Payload { 19 | fn base(self) -> u32 { 20 | match self { 21 | Payload::LinkLayer(_) => libc::NFT_PAYLOAD_LL_HEADER as u32, 22 | Payload::Network(_) => libc::NFT_PAYLOAD_NETWORK_HEADER as u32, 23 | Payload::Transport(_) => libc::NFT_PAYLOAD_TRANSPORT_HEADER as u32, 24 | } 25 | } 26 | } 27 | 28 | impl HeaderField for Payload { 29 | fn offset(&self) -> u32 { 30 | use self::Payload::*; 31 | match *self { 32 | LinkLayer(ref f) => f.offset(), 33 | Network(ref f) => f.offset(), 34 | Transport(ref f) => f.offset(), 35 | } 36 | } 37 | 38 | fn len(&self) -> u32 { 39 | use self::Payload::*; 40 | match *self { 41 | LinkLayer(ref f) => f.len(), 42 | Network(ref f) => f.len(), 43 | Transport(ref f) => f.len(), 44 | } 45 | } 46 | } 47 | 48 | impl Expression for Payload { 49 | fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr { 50 | unsafe { 51 | let expr = try_alloc!(sys::nftnl_expr_alloc( 52 | b"payload\0" as *const _ as *const c_char 53 | )); 54 | 55 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_PAYLOAD_BASE as u16, self.base()); 56 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_PAYLOAD_OFFSET as u16, self.offset()); 57 | sys::nftnl_expr_set_u32(expr, sys::NFTNL_EXPR_PAYLOAD_LEN as u16, self.len()); 58 | sys::nftnl_expr_set_u32( 59 | expr, 60 | sys::NFTNL_EXPR_PAYLOAD_DREG as u16, 61 | libc::NFT_REG_1 as u32, 62 | ); 63 | 64 | expr 65 | } 66 | } 67 | } 68 | 69 | #[derive(Copy, Clone, Eq, PartialEq)] 70 | #[non_exhaustive] 71 | pub enum LLHeaderField { 72 | Daddr, 73 | Saddr, 74 | EtherType, 75 | Raw { offset_bits: u32, length_bits: u32 }, 76 | } 77 | 78 | impl HeaderField for LLHeaderField { 79 | fn offset(&self) -> u32 { 80 | use self::LLHeaderField::*; 81 | match *self { 82 | Daddr => 0, 83 | Saddr => 6, 84 | EtherType => 12, 85 | Raw { offset_bits, .. } => offset_bits, 86 | } 87 | } 88 | 89 | fn len(&self) -> u32 { 90 | use self::LLHeaderField::*; 91 | match *self { 92 | Daddr => 6, 93 | Saddr => 6, 94 | EtherType => 2, 95 | Raw { length_bits, .. } => length_bits, 96 | } 97 | } 98 | } 99 | 100 | #[derive(Copy, Clone, Eq, PartialEq)] 101 | pub enum NetworkHeaderField { 102 | Ipv4(Ipv4HeaderField), 103 | Ipv6(Ipv6HeaderField), 104 | Raw { offset_bits: u32, length_bits: u32 }, 105 | } 106 | 107 | impl HeaderField for NetworkHeaderField { 108 | fn offset(&self) -> u32 { 109 | use self::NetworkHeaderField::*; 110 | match *self { 111 | Ipv4(ref f) => f.offset(), 112 | Ipv6(ref f) => f.offset(), 113 | Raw { offset_bits, .. } => offset_bits, 114 | } 115 | } 116 | 117 | fn len(&self) -> u32 { 118 | use self::NetworkHeaderField::*; 119 | match *self { 120 | Ipv4(ref f) => f.len(), 121 | Ipv6(ref f) => f.len(), 122 | Raw { length_bits, .. } => length_bits, 123 | } 124 | } 125 | } 126 | 127 | #[derive(Copy, Clone, Eq, PartialEq)] 128 | #[non_exhaustive] 129 | pub enum Ipv4HeaderField { 130 | Ttl, 131 | Protocol, 132 | Saddr, 133 | Daddr, 134 | } 135 | 136 | impl HeaderField for Ipv4HeaderField { 137 | fn offset(&self) -> u32 { 138 | use self::Ipv4HeaderField::*; 139 | match *self { 140 | Ttl => 8, 141 | Protocol => 9, 142 | Saddr => 12, 143 | Daddr => 16, 144 | } 145 | } 146 | 147 | fn len(&self) -> u32 { 148 | use self::Ipv4HeaderField::*; 149 | match *self { 150 | Ttl => 1, 151 | Protocol => 1, 152 | Saddr => 4, 153 | Daddr => 4, 154 | } 155 | } 156 | } 157 | 158 | #[derive(Copy, Clone, Eq, PartialEq)] 159 | #[non_exhaustive] 160 | pub enum Ipv6HeaderField { 161 | NextHeader, 162 | HopLimit, 163 | Saddr, 164 | Daddr, 165 | } 166 | 167 | impl HeaderField for Ipv6HeaderField { 168 | fn offset(&self) -> u32 { 169 | use self::Ipv6HeaderField::*; 170 | match *self { 171 | NextHeader => 6, 172 | HopLimit => 7, 173 | Saddr => 8, 174 | Daddr => 24, 175 | } 176 | } 177 | 178 | fn len(&self) -> u32 { 179 | use self::Ipv6HeaderField::*; 180 | match *self { 181 | NextHeader => 1, 182 | HopLimit => 1, 183 | Saddr => 16, 184 | Daddr => 16, 185 | } 186 | } 187 | } 188 | 189 | #[derive(Copy, Clone, Eq, PartialEq)] 190 | #[non_exhaustive] 191 | pub enum TransportHeaderField { 192 | Tcp(TcpHeaderField), 193 | Udp(UdpHeaderField), 194 | Icmpv6(Icmpv6HeaderField), 195 | Raw { offset_bits: u32, length_bits: u32 }, 196 | } 197 | 198 | impl HeaderField for TransportHeaderField { 199 | fn offset(&self) -> u32 { 200 | use self::TransportHeaderField::*; 201 | match *self { 202 | Tcp(ref f) => f.offset(), 203 | Udp(ref f) => f.offset(), 204 | Icmpv6(ref f) => f.offset(), 205 | Raw { offset_bits, .. } => offset_bits, 206 | } 207 | } 208 | 209 | fn len(&self) -> u32 { 210 | use self::TransportHeaderField::*; 211 | match *self { 212 | Tcp(ref f) => f.len(), 213 | Udp(ref f) => f.len(), 214 | Icmpv6(ref f) => f.len(), 215 | Raw { length_bits, .. } => length_bits, 216 | } 217 | } 218 | } 219 | 220 | #[derive(Copy, Clone, Eq, PartialEq)] 221 | #[non_exhaustive] 222 | pub enum TcpHeaderField { 223 | Sport, 224 | Dport, 225 | } 226 | 227 | impl HeaderField for TcpHeaderField { 228 | fn offset(&self) -> u32 { 229 | use self::TcpHeaderField::*; 230 | match *self { 231 | Sport => 0, 232 | Dport => 2, 233 | } 234 | } 235 | 236 | fn len(&self) -> u32 { 237 | use self::TcpHeaderField::*; 238 | match *self { 239 | Sport => 2, 240 | Dport => 2, 241 | } 242 | } 243 | } 244 | 245 | #[derive(Copy, Clone, Eq, PartialEq)] 246 | #[non_exhaustive] 247 | pub enum UdpHeaderField { 248 | Sport, 249 | Dport, 250 | Len, 251 | } 252 | 253 | impl HeaderField for UdpHeaderField { 254 | fn offset(&self) -> u32 { 255 | use self::UdpHeaderField::*; 256 | match *self { 257 | Sport => 0, 258 | Dport => 2, 259 | Len => 4, 260 | } 261 | } 262 | 263 | fn len(&self) -> u32 { 264 | use self::UdpHeaderField::*; 265 | match *self { 266 | Sport => 2, 267 | Dport => 2, 268 | Len => 2, 269 | } 270 | } 271 | } 272 | 273 | #[derive(Copy, Clone, Eq, PartialEq)] 274 | #[non_exhaustive] 275 | pub enum Icmpv6HeaderField { 276 | Type, 277 | Code, 278 | Checksum, 279 | } 280 | 281 | impl HeaderField for Icmpv6HeaderField { 282 | fn offset(&self) -> u32 { 283 | use self::Icmpv6HeaderField::*; 284 | match *self { 285 | Type => 0, 286 | Code => 1, 287 | Checksum => 2, 288 | } 289 | } 290 | 291 | fn len(&self) -> u32 { 292 | use self::Icmpv6HeaderField::*; 293 | match *self { 294 | Type => 1, 295 | Code => 1, 296 | Checksum => 2, 297 | } 298 | } 299 | } 300 | 301 | #[macro_export(local_inner_macros)] 302 | macro_rules! nft_expr_payload { 303 | (@ipv4_field ttl) => { 304 | $crate::expr::Ipv4HeaderField::Ttl 305 | }; 306 | (@ipv4_field protocol) => { 307 | $crate::expr::Ipv4HeaderField::Protocol 308 | }; 309 | (@ipv4_field saddr) => { 310 | $crate::expr::Ipv4HeaderField::Saddr 311 | }; 312 | (@ipv4_field daddr) => { 313 | $crate::expr::Ipv4HeaderField::Daddr 314 | }; 315 | 316 | (@ipv6_field nextheader) => { 317 | $crate::expr::Ipv6HeaderField::NextHeader 318 | }; 319 | (@ipv6_field hoplimit) => { 320 | $crate::expr::Ipv6HeaderField::HopLimit 321 | }; 322 | (@ipv6_field saddr) => { 323 | $crate::expr::Ipv6HeaderField::Saddr 324 | }; 325 | (@ipv6_field daddr) => { 326 | $crate::expr::Ipv6HeaderField::Daddr 327 | }; 328 | 329 | (@tcp_field sport) => { 330 | $crate::expr::TcpHeaderField::Sport 331 | }; 332 | (@tcp_field dport) => { 333 | $crate::expr::TcpHeaderField::Dport 334 | }; 335 | 336 | (@udp_field sport) => { 337 | $crate::expr::UdpHeaderField::Sport 338 | }; 339 | (@udp_field dport) => { 340 | $crate::expr::UdpHeaderField::Dport 341 | }; 342 | (@udp_field len) => { 343 | $crate::expr::UdpHeaderField::Len 344 | }; 345 | 346 | (ll $offset:expr, $length:expr) => { 347 | $crate::expr::Payload::LinkLayer($crate::expr::LLHeaderField::Raw { offset_bits: $offset, length_bits: $length }) 348 | }; 349 | 350 | (ethernet daddr) => { 351 | $crate::expr::Payload::LinkLayer($crate::expr::LLHeaderField::Daddr) 352 | }; 353 | (ethernet saddr) => { 354 | $crate::expr::Payload::LinkLayer($crate::expr::LLHeaderField::Saddr) 355 | }; 356 | (ethernet ethertype) => { 357 | $crate::expr::Payload::LinkLayer($crate::expr::LLHeaderField::EtherType) 358 | }; 359 | 360 | (nh $offset:expr, $length:expr) => { 361 | $crate::expr::Payload::Network($crate::expr::NetworkHeaderField::Raw { offset_bits: $offset, length_bits: $length }) 362 | }; 363 | 364 | (ipv4 $field:ident) => { 365 | $crate::expr::Payload::Network($crate::expr::NetworkHeaderField::Ipv4( 366 | nft_expr_payload!(@ipv4_field $field), 367 | )) 368 | }; 369 | (ipv6 $field:ident) => { 370 | $crate::expr::Payload::Network($crate::expr::NetworkHeaderField::Ipv6( 371 | nft_expr_payload!(@ipv6_field $field), 372 | )) 373 | }; 374 | 375 | (th $offset:expr, $length:expr) => { 376 | $crate::expr::Payload::Transport($crate::expr::TransportHeaderField::Raw { offset_bits: $offset, length_bits: $length }) 377 | }; 378 | 379 | (tcp $field:ident) => { 380 | $crate::expr::Payload::Transport($crate::expr::TransportHeaderField::Tcp( 381 | nft_expr_payload!(@tcp_field $field), 382 | )) 383 | }; 384 | (udp $field:ident) => { 385 | $crate::expr::Payload::Transport($crate::expr::TransportHeaderField::Udp( 386 | nft_expr_payload!(@udp_field $field), 387 | )) 388 | }; 389 | } 390 | -------------------------------------------------------------------------------- /nftnl/src/expr/verdict.rs: -------------------------------------------------------------------------------- 1 | use super::{Expression, Rule}; 2 | use crate::ProtoFamily; 3 | use nftnl_sys::{ 4 | self as sys, 5 | libc::{self, c_char}, 6 | }; 7 | use std::ffi::{CStr, CString}; 8 | 9 | /// A verdict expression. In the background, this is usually an "Immediate" expression in nftnl 10 | /// terms, but here it is simplified to only represent a verdict. 11 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 12 | pub enum Verdict { 13 | /// Silently drop the packet. 14 | Drop, 15 | /// Accept the packet and let it pass. 16 | Accept, 17 | /// Reject the packet and return a message. 18 | Reject(RejectionType), 19 | Queue, 20 | Continue, 21 | Break, 22 | Jump { 23 | chain: CString, 24 | }, 25 | Goto { 26 | chain: CString, 27 | }, 28 | Return, 29 | } 30 | 31 | /// The type of rejection message sent by the Reject verdict. 32 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 33 | pub enum RejectionType { 34 | /// Return an ICMP unreachable packet 35 | Icmp(IcmpCode), 36 | /// Reject by sending a TCP RST packet 37 | TcpRst, 38 | } 39 | 40 | impl RejectionType { 41 | fn to_raw(self, family: ProtoFamily) -> u32 { 42 | use libc::*; 43 | let value = match self { 44 | RejectionType::Icmp(..) => match family { 45 | ProtoFamily::Bridge | ProtoFamily::Inet => NFT_REJECT_ICMPX_UNREACH, 46 | _ => NFT_REJECT_ICMP_UNREACH, 47 | }, 48 | RejectionType::TcpRst => NFT_REJECT_TCP_RST, 49 | }; 50 | value as u32 51 | } 52 | } 53 | 54 | /// An ICMP reject code. 55 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 56 | #[repr(u8)] 57 | pub enum IcmpCode { 58 | NoRoute = libc::NFT_REJECT_ICMPX_NO_ROUTE as u8, 59 | PortUnreach = libc::NFT_REJECT_ICMPX_PORT_UNREACH as u8, 60 | HostUnreach = libc::NFT_REJECT_ICMPX_HOST_UNREACH as u8, 61 | AdminProhibited = libc::NFT_REJECT_ICMPX_ADMIN_PROHIBITED as u8, 62 | } 63 | 64 | impl Verdict { 65 | unsafe fn to_immediate_expr(&self, immediate_const: i32) -> *mut sys::nftnl_expr { 66 | let expr = try_alloc!(sys::nftnl_expr_alloc( 67 | b"immediate\0" as *const _ as *const c_char 68 | )); 69 | 70 | sys::nftnl_expr_set_u32( 71 | expr, 72 | sys::NFTNL_EXPR_IMM_DREG as u16, 73 | libc::NFT_REG_VERDICT as u32, 74 | ); 75 | 76 | if let Some(chain) = self.chain() { 77 | sys::nftnl_expr_set_str(expr, sys::NFTNL_EXPR_IMM_CHAIN as u16, chain.as_ptr()); 78 | } 79 | sys::nftnl_expr_set_u32( 80 | expr, 81 | sys::NFTNL_EXPR_IMM_VERDICT as u16, 82 | immediate_const as u32, 83 | ); 84 | 85 | expr 86 | } 87 | 88 | unsafe fn to_reject_expr( 89 | &self, 90 | reject_type: RejectionType, 91 | family: ProtoFamily, 92 | ) -> *mut sys::nftnl_expr { 93 | let expr = try_alloc!(sys::nftnl_expr_alloc( 94 | b"reject\0" as *const _ as *const c_char 95 | )); 96 | 97 | sys::nftnl_expr_set_u32( 98 | expr, 99 | sys::NFTNL_EXPR_REJECT_TYPE as u16, 100 | reject_type.to_raw(family), 101 | ); 102 | 103 | let reject_code = match reject_type { 104 | RejectionType::Icmp(code) => code as u8, 105 | RejectionType::TcpRst => 0, 106 | }; 107 | 108 | sys::nftnl_expr_set_u8(expr, sys::NFTNL_EXPR_REJECT_CODE as u16, reject_code); 109 | 110 | expr 111 | } 112 | 113 | fn chain(&self) -> Option<&CStr> { 114 | match *self { 115 | Verdict::Jump { ref chain } => Some(chain.as_c_str()), 116 | Verdict::Goto { ref chain } => Some(chain.as_c_str()), 117 | _ => None, 118 | } 119 | } 120 | } 121 | 122 | impl Expression for Verdict { 123 | fn to_expr(&self, rule: &Rule) -> *mut sys::nftnl_expr { 124 | let immediate_const = match *self { 125 | Verdict::Drop => libc::NF_DROP, 126 | Verdict::Accept => libc::NF_ACCEPT, 127 | Verdict::Queue => libc::NF_QUEUE, 128 | Verdict::Continue => libc::NFT_CONTINUE, 129 | Verdict::Break => libc::NFT_BREAK, 130 | Verdict::Jump { .. } => libc::NFT_JUMP, 131 | Verdict::Goto { .. } => libc::NFT_GOTO, 132 | Verdict::Return => libc::NFT_RETURN, 133 | Verdict::Reject(reject_type) => { 134 | return unsafe { 135 | self.to_reject_expr(reject_type, rule.get_chain().get_table().get_family()) 136 | } 137 | } 138 | }; 139 | unsafe { self.to_immediate_expr(immediate_const) } 140 | } 141 | } 142 | 143 | #[macro_export] 144 | macro_rules! nft_expr_verdict { 145 | (drop) => { 146 | $crate::expr::Verdict::Drop 147 | }; 148 | (accept) => { 149 | $crate::expr::Verdict::Accept 150 | }; 151 | (reject icmp $code:expr) => { 152 | $crate::expr::Verdict::Reject(RejectionType::Icmp($code)) 153 | }; 154 | (reject tcp-rst) => { 155 | $crate::expr::Verdict::Reject(RejectionType::TcpRst) 156 | }; 157 | (queue) => { 158 | $crate::expr::Verdict::Queue 159 | }; 160 | (continue) => { 161 | $crate::expr::Verdict::Continue 162 | }; 163 | (break) => { 164 | $crate::expr::Verdict::Break 165 | }; 166 | (jump $chain:expr) => { 167 | $crate::expr::Verdict::Jump { chain: $chain } 168 | }; 169 | (goto $chain:expr) => { 170 | $crate::expr::Verdict::Goto { chain: $chain } 171 | }; 172 | (return) => { 173 | $crate::expr::Verdict::Return 174 | }; 175 | } 176 | -------------------------------------------------------------------------------- /nftnl/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amagicom AB. 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Safe abstraction for [`libnftnl`]. Provides low-level userspace access to the in-kernel 10 | //! nf_tables subsystem. See [`nftnl-sys`] for the low level FFI bindings to the C library. 11 | //! 12 | //! Can be used to create and remove tables, chains, sets and rules from the nftables firewall, 13 | //! the successor to iptables. 14 | //! 15 | //! This library currently has quite rough edges and does not make adding and removing netfilter 16 | //! entries super easy and elegant. That is partly because the library needs more work, but also 17 | //! partly because nftables is super low level and extremely customizable, making it hard, and 18 | //! probably wrong, to try and create a too simple/limited wrapper. See examples for inspiration. 19 | //! One can also look at how the original project this crate was developed to support uses it: 20 | //! [Mullvad VPN app](https://github.com/mullvad/mullvadvpn-app) 21 | //! 22 | //! Understanding how to use [`libnftnl`] and implementing this crate has mostly been done by 23 | //! reading the source code for the [`nftables`] program and attaching debuggers to the `nft` 24 | //! binary. Since the implementation is mostly based on trial and error, there might of course be 25 | //! a number of places where the underlying library is used in an invalid or not intended way. 26 | //! Large portions of [`libnftnl`] are also not covered yet. Contributions are welcome! 27 | //! 28 | //! # Selecting version of `libnftnl` 29 | //! 30 | //! See the documentation for the corresponding sys crate for details: [`nftnl-sys`] 31 | //! This crate has the same features as the sys crate, and selecting version works the same. 32 | //! 33 | //! [`libnftnl`]: https://netfilter.org/projects/libnftnl/ 34 | //! [`nftables`]: https://netfilter.org/projects/nftables/ 35 | //! [`nftnl-sys`]: https://crates.io/crates/nftnl-sys 36 | 37 | #[macro_use] 38 | extern crate log; 39 | 40 | pub use nftnl_sys; 41 | use nftnl_sys::libc; 42 | use std::ffi::c_void; 43 | 44 | macro_rules! try_alloc { 45 | ($e:expr) => {{ 46 | let ptr = $e; 47 | if ptr.is_null() { 48 | // OOM, and the tried allocation was likely very small, 49 | // so we are in a very tight situation. We do what libstd does, aborts. 50 | std::process::abort(); 51 | } 52 | ptr 53 | }}; 54 | } 55 | 56 | mod batch; 57 | pub use batch::{batch_is_supported, default_batch_page_size, Batch, FinalizedBatch, NetlinkError}; 58 | 59 | pub mod expr; 60 | 61 | pub mod table; 62 | pub use table::Table; 63 | 64 | mod chain; 65 | pub use chain::{Chain, ChainType, Hook, Policy, Priority}; 66 | 67 | mod rule; 68 | pub use rule::Rule; 69 | 70 | pub mod set; 71 | 72 | /// The type of the message as it's sent to netfilter. A message consists of an object, such as a 73 | /// [`Table`], [`Chain`] or [`Rule`] for example, and a [`MsgType`] to describe what to do with 74 | /// that object. If a [`Table`] object is sent with `MsgType::Add` then that table will be added 75 | /// to netfilter, if sent with `MsgType::Del` it will be removed. 76 | /// 77 | /// [`Table`]: struct.Table.html 78 | /// [`Chain`]: struct.Chain.html 79 | /// [`Rule`]: struct.Rule.html 80 | /// [`MsgType`]: enum.MsgType.html 81 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 82 | pub enum MsgType { 83 | /// Add the object to netfilter. 84 | Add, 85 | /// Remove the object from netfilter. 86 | Del, 87 | } 88 | 89 | /// Denotes a protocol. Used to specify which protocol a table or set belongs to. 90 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 91 | #[repr(u16)] 92 | pub enum ProtoFamily { 93 | Unspec = libc::NFPROTO_UNSPEC as u16, 94 | /// Inet - Means both IPv4 and IPv6 95 | Inet = libc::NFPROTO_INET as u16, 96 | Ipv4 = libc::NFPROTO_IPV4 as u16, 97 | Arp = libc::NFPROTO_ARP as u16, 98 | NetDev = libc::NFPROTO_NETDEV as u16, 99 | Bridge = libc::NFPROTO_BRIDGE as u16, 100 | Ipv6 = libc::NFPROTO_IPV6 as u16, 101 | DecNet = libc::NFPROTO_DECNET as u16, 102 | } 103 | 104 | /// Trait for all types in this crate that can serialize to a Netlink message. 105 | /// 106 | /// # Safety 107 | /// 108 | /// This trait is unsafe to implement because it must never serialize to anything larger than the 109 | /// largest possible netlink message. Internally the [`nft_nlmsg_maxsize`] function is used to make 110 | /// sure the `buf` pointer passed to `write` always has room for the largest possible Netlink 111 | /// message. 112 | pub unsafe trait NlMsg { 113 | /// Serializes the Netlink message to the buffer at `buf`. `buf` must have space for at least 114 | /// `nft_nlmsg_maxsize()` bytes. This is not checked by the compiler, which is why this method 115 | /// is unsafe. 116 | /// 117 | /// # Safety 118 | /// 119 | /// The caller must pass a `buf` with enough space for the largest possible netlink message. 120 | /// This size can be obtained with [`nft_nlmsg_maxsize`]. 121 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType); 122 | } 123 | 124 | /// The largest nf_tables netlink message is the set element message, which 125 | /// contains the NFTA_SET_ELEM_LIST_ELEMENTS attribute. This attribute is 126 | /// a nest that describes the set elements. Given that the netlink attribute 127 | /// length (nla_len) is 16 bits, the largest message is a bit larger than 128 | /// 64 KBytes. 129 | pub fn nft_nlmsg_maxsize() -> u32 { 130 | u32::from(u16::MAX) + unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u32 131 | } 132 | -------------------------------------------------------------------------------- /nftnl/src/rule.rs: -------------------------------------------------------------------------------- 1 | use crate::{chain::Chain, expr::Expression, MsgType}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::ffi::c_void; 4 | use std::os::raw::c_char; 5 | 6 | /// A nftables firewall rule. 7 | pub struct Rule<'a> { 8 | rule: *mut sys::nftnl_rule, 9 | chain: &'a Chain<'a>, 10 | } 11 | 12 | // Safety: It should be safe to pass this around and *read* from it 13 | // from multiple threads 14 | unsafe impl Send for Rule<'_> {} 15 | unsafe impl Sync for Rule<'_> {} 16 | 17 | impl<'a> Rule<'a> { 18 | /// Creates a new rule object in the given [`Chain`]. 19 | /// 20 | /// [`Chain`]: struct.Chain.html 21 | pub fn new(chain: &'a Chain<'_>) -> Rule<'a> { 22 | unsafe { 23 | let rule = try_alloc!(sys::nftnl_rule_alloc()); 24 | sys::nftnl_rule_set_u32( 25 | rule, 26 | sys::NFTNL_RULE_FAMILY as u16, 27 | chain.get_table().get_family() as u32, 28 | ); 29 | sys::nftnl_rule_set_str( 30 | rule, 31 | sys::NFTNL_RULE_TABLE as u16, 32 | chain.get_table().get_name().as_ptr(), 33 | ); 34 | sys::nftnl_rule_set_str( 35 | rule, 36 | sys::NFTNL_RULE_CHAIN as u16, 37 | chain.get_name().as_ptr(), 38 | ); 39 | 40 | Rule { rule, chain } 41 | } 42 | } 43 | 44 | /// Sets the position of this rule within the chain it lives in. By default a new rule is added 45 | /// to the end of the chain. 46 | pub fn set_position(&mut self, position: u64) { 47 | unsafe { 48 | sys::nftnl_rule_set_u64(self.rule, sys::NFTNL_RULE_POSITION as u16, position); 49 | } 50 | } 51 | 52 | pub fn set_handle(&mut self, handle: u64) { 53 | unsafe { 54 | sys::nftnl_rule_set_u64(self.rule, sys::NFTNL_RULE_HANDLE as u16, handle); 55 | } 56 | } 57 | 58 | /// Adds an expression to this rule. Expressions are evaluated from first to last added. 59 | /// As soon as an expression does not match the packet it's being evaluated for, evaluation 60 | /// stops and the packet is evaluated against the next rule in the chain. 61 | pub fn add_expr(&mut self, expr: &impl Expression) { 62 | unsafe { sys::nftnl_rule_add_expr(self.rule, expr.to_expr(self)) } 63 | } 64 | 65 | /// Returns a reference to the [`Chain`] this rule lives in. 66 | /// 67 | /// [`Chain`]: struct.Chain.html 68 | pub fn get_chain(&self) -> &Chain<'_> { 69 | self.chain 70 | } 71 | } 72 | 73 | unsafe impl crate::NlMsg for Rule<'_> { 74 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType) { 75 | let type_ = match msg_type { 76 | MsgType::Add => libc::NFT_MSG_NEWRULE, 77 | MsgType::Del => libc::NFT_MSG_DELRULE, 78 | }; 79 | let flags: u16 = match msg_type { 80 | MsgType::Add => (libc::NLM_F_CREATE | libc::NLM_F_APPEND | libc::NLM_F_EXCL) as u16, 81 | MsgType::Del => 0u16, 82 | }; 83 | let header = sys::nftnl_nlmsg_build_hdr( 84 | buf as *mut c_char, 85 | type_ as u16, 86 | self.chain.get_table().get_family() as u16, 87 | flags, 88 | seq, 89 | ); 90 | sys::nftnl_rule_nlmsg_build_payload(header, self.rule); 91 | } 92 | } 93 | 94 | impl Drop for Rule<'_> { 95 | fn drop(&mut self) { 96 | unsafe { sys::nftnl_rule_free(self.rule) }; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /nftnl/src/set.rs: -------------------------------------------------------------------------------- 1 | use crate::{table::Table, MsgType, ProtoFamily}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::{ 4 | cell::Cell, 5 | ffi::{c_void, CStr}, 6 | net::{Ipv4Addr, Ipv6Addr}, 7 | os::raw::c_char, 8 | rc::Rc, 9 | }; 10 | 11 | #[macro_export] 12 | macro_rules! nft_set { 13 | ($name:expr, $id:expr, $table:expr, $family:expr) => { 14 | $crate::set::Set::new($name, $id, $table, $family) 15 | }; 16 | ($name:expr, $id:expr, $table:expr, $family:expr; [ ]) => { 17 | nft_set!($name, $id, $table, $family) 18 | }; 19 | ($name:expr, $id:expr, $table:expr, $family:expr; [ $($value:expr,)* ]) => {{ 20 | let mut set = nft_set!($name, $id, $table, $family); 21 | $( 22 | set.add($value); 23 | )* 24 | set 25 | }}; 26 | } 27 | 28 | pub struct Set<'a, K> { 29 | set: *mut sys::nftnl_set, 30 | table: &'a Table, 31 | family: ProtoFamily, 32 | _marker: ::std::marker::PhantomData, 33 | } 34 | 35 | impl<'a, K> Set<'a, K> { 36 | pub fn new(name: &CStr, id: u32, table: &'a Table, family: ProtoFamily) -> Self 37 | where 38 | K: SetKey, 39 | { 40 | unsafe { 41 | let set = try_alloc!(sys::nftnl_set_alloc()); 42 | 43 | sys::nftnl_set_set_u32(set, sys::NFTNL_SET_FAMILY as u16, family as u32); 44 | sys::nftnl_set_set_str(set, sys::NFTNL_SET_TABLE as u16, table.get_name().as_ptr()); 45 | sys::nftnl_set_set_str(set, sys::NFTNL_SET_NAME as u16, name.as_ptr()); 46 | sys::nftnl_set_set_u32(set, sys::NFTNL_SET_ID as u16, id); 47 | 48 | sys::nftnl_set_set_u32( 49 | set, 50 | sys::NFTNL_SET_FLAGS as u16, 51 | (libc::NFT_SET_ANONYMOUS | libc::NFT_SET_CONSTANT) as u32, 52 | ); 53 | sys::nftnl_set_set_u32(set, sys::NFTNL_SET_KEY_TYPE as u16, K::TYPE); 54 | sys::nftnl_set_set_u32(set, sys::NFTNL_SET_KEY_LEN as u16, K::LEN); 55 | 56 | Set { 57 | set, 58 | table, 59 | family, 60 | _marker: ::std::marker::PhantomData, 61 | } 62 | } 63 | } 64 | 65 | pub fn add(&mut self, key: &K) 66 | where 67 | K: SetKey, 68 | { 69 | unsafe { 70 | let elem = try_alloc!(sys::nftnl_set_elem_alloc()); 71 | 72 | let data = key.data(); 73 | let data_len = data.len() as u32; 74 | trace!("Adding key {:?} with len {}", data, data_len); 75 | sys::nftnl_set_elem_set( 76 | elem, 77 | sys::NFTNL_SET_ELEM_KEY as u16, 78 | data.as_ref() as *const _ as *const c_void, 79 | data_len, 80 | ); 81 | sys::nftnl_set_elem_add(self.set, elem); 82 | } 83 | } 84 | 85 | pub fn elems_iter(&'a self) -> SetElemsIter<'a, K> { 86 | SetElemsIter::new(self) 87 | } 88 | 89 | pub fn as_ptr(&self) -> *mut sys::nftnl_set { 90 | self.set 91 | } 92 | 93 | pub fn get_family(&self) -> ProtoFamily { 94 | self.family 95 | } 96 | 97 | pub fn get_name(&self) -> &CStr { 98 | unsafe { 99 | let ptr = sys::nftnl_set_get_str(self.set, sys::NFTNL_SET_NAME as u16); 100 | CStr::from_ptr(ptr) 101 | } 102 | } 103 | 104 | pub fn get_id(&self) -> u32 { 105 | unsafe { sys::nftnl_set_get_u32(self.set, sys::NFTNL_SET_ID as u16) } 106 | } 107 | } 108 | 109 | unsafe impl crate::NlMsg for Set<'_, K> { 110 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType) { 111 | let type_ = match msg_type { 112 | MsgType::Add => libc::NFT_MSG_NEWSET, 113 | MsgType::Del => libc::NFT_MSG_DELSET, 114 | }; 115 | let header = sys::nftnl_nlmsg_build_hdr( 116 | buf as *mut c_char, 117 | type_ as u16, 118 | self.table.get_family() as u16, 119 | (libc::NLM_F_APPEND | libc::NLM_F_CREATE | libc::NLM_F_ACK) as u16, 120 | seq, 121 | ); 122 | sys::nftnl_set_nlmsg_build_payload(header, self.set); 123 | } 124 | } 125 | 126 | impl Drop for Set<'_, K> { 127 | fn drop(&mut self) { 128 | unsafe { sys::nftnl_set_free(self.set) }; 129 | } 130 | } 131 | 132 | pub struct SetElemsIter<'a, K> { 133 | set: &'a Set<'a, K>, 134 | iter: *mut sys::nftnl_set_elems_iter, 135 | ret: Rc>, 136 | } 137 | 138 | impl<'a, K> SetElemsIter<'a, K> { 139 | fn new(set: &'a Set<'a, K>) -> Self { 140 | let iter = try_alloc!(unsafe { sys::nftnl_set_elems_iter_create(set.as_ptr()) }); 141 | SetElemsIter { 142 | set, 143 | iter, 144 | ret: Rc::new(Cell::new(1)), 145 | } 146 | } 147 | } 148 | 149 | impl<'a, K: 'a> Iterator for SetElemsIter<'a, K> { 150 | type Item = SetElemsMsg<'a, K>; 151 | 152 | fn next(&mut self) -> Option { 153 | if self.ret.get() <= 0 || unsafe { sys::nftnl_set_elems_iter_cur(self.iter).is_null() } { 154 | trace!("SetElemsIter iterator ending"); 155 | None 156 | } else { 157 | trace!("SetElemsIter returning new SetElemsMsg"); 158 | Some(SetElemsMsg { 159 | set: self.set, 160 | iter: self.iter, 161 | ret: self.ret.clone(), 162 | }) 163 | } 164 | } 165 | } 166 | 167 | impl Drop for SetElemsIter<'_, K> { 168 | fn drop(&mut self) { 169 | unsafe { sys::nftnl_set_elems_iter_destroy(self.iter) }; 170 | } 171 | } 172 | 173 | pub struct SetElemsMsg<'a, K> { 174 | set: &'a Set<'a, K>, 175 | iter: *mut sys::nftnl_set_elems_iter, 176 | ret: Rc>, 177 | } 178 | 179 | unsafe impl crate::NlMsg for SetElemsMsg<'_, K> { 180 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType) { 181 | trace!("Writing SetElemsMsg to NlMsg"); 182 | let (type_, flags) = match msg_type { 183 | MsgType::Add => ( 184 | libc::NFT_MSG_NEWSETELEM, 185 | libc::NLM_F_CREATE | libc::NLM_F_EXCL | libc::NLM_F_ACK, 186 | ), 187 | MsgType::Del => (libc::NFT_MSG_DELSETELEM, libc::NLM_F_ACK), 188 | }; 189 | let header = sys::nftnl_nlmsg_build_hdr( 190 | buf as *mut c_char, 191 | type_ as u16, 192 | self.set.get_family() as u16, 193 | flags as u16, 194 | seq, 195 | ); 196 | self.ret.set(sys::nftnl_set_elems_nlmsg_build_payload_iter( 197 | header, self.iter, 198 | )); 199 | } 200 | } 201 | 202 | pub trait SetKey { 203 | const TYPE: u32; 204 | const LEN: u32; 205 | 206 | fn data(&self) -> Box<[u8]>; 207 | } 208 | 209 | impl SetKey for Ipv4Addr { 210 | const TYPE: u32 = 7; 211 | const LEN: u32 = 4; 212 | 213 | fn data(&self) -> Box<[u8]> { 214 | self.octets().to_vec().into_boxed_slice() 215 | } 216 | } 217 | 218 | impl SetKey for Ipv6Addr { 219 | const TYPE: u32 = 8; 220 | const LEN: u32 = 16; 221 | 222 | fn data(&self) -> Box<[u8]> { 223 | self.octets().to_vec().into_boxed_slice() 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /nftnl/src/table.rs: -------------------------------------------------------------------------------- 1 | use crate::{MsgType, ProtoFamily}; 2 | use nftnl_sys::{self as sys, libc}; 3 | use std::{ 4 | collections::HashSet, 5 | ffi::{c_void, CStr, CString}, 6 | os::raw::c_char, 7 | }; 8 | 9 | /// Abstraction of `nftnl_table`. The top level container in netfilter. A table has a protocol 10 | /// family and contain [`Chain`]s that in turn hold the rules. 11 | /// 12 | /// [`Chain`]: struct.Chain.html 13 | pub struct Table { 14 | table: *mut sys::nftnl_table, 15 | family: ProtoFamily, 16 | } 17 | 18 | // Safety: It should be safe to pass this around and *read* from it 19 | // from multiple threads 20 | unsafe impl Send for Table {} 21 | unsafe impl Sync for Table {} 22 | 23 | impl Table { 24 | /// Creates a new table instance with the given name and protocol family. 25 | pub fn new>(name: &T, family: ProtoFamily) -> Table { 26 | unsafe { 27 | let table = try_alloc!(sys::nftnl_table_alloc()); 28 | 29 | sys::nftnl_table_set_u32(table, sys::NFTNL_TABLE_FAMILY as u16, family as u32); 30 | sys::nftnl_table_set_str(table, sys::NFTNL_TABLE_NAME as u16, name.as_ref().as_ptr()); 31 | sys::nftnl_table_set_u32(table, sys::NFTNL_TABLE_FLAGS as u16, 0u32); 32 | Table { table, family } 33 | } 34 | } 35 | 36 | /// Returns the name of this table. 37 | pub fn get_name(&self) -> &CStr { 38 | unsafe { 39 | let ptr = sys::nftnl_table_get_str(self.table, sys::NFTNL_TABLE_NAME as u16); 40 | CStr::from_ptr(ptr) 41 | } 42 | } 43 | 44 | /// Returns the protocol family for this table. 45 | pub fn get_family(&self) -> ProtoFamily { 46 | self.family 47 | } 48 | } 49 | 50 | unsafe impl crate::NlMsg for Table { 51 | unsafe fn write(&self, buf: *mut c_void, seq: u32, msg_type: MsgType) { 52 | let raw_msg_type = match msg_type { 53 | MsgType::Add => libc::NFT_MSG_NEWTABLE, 54 | MsgType::Del => libc::NFT_MSG_DELTABLE, 55 | }; 56 | let header = sys::nftnl_nlmsg_build_hdr( 57 | buf as *mut c_char, 58 | raw_msg_type as u16, 59 | self.family as u16, 60 | libc::NLM_F_ACK as u16, 61 | seq, 62 | ); 63 | sys::nftnl_table_nlmsg_build_payload(header, self.table); 64 | } 65 | } 66 | 67 | impl Drop for Table { 68 | fn drop(&mut self) { 69 | unsafe { sys::nftnl_table_free(self.table) }; 70 | } 71 | } 72 | 73 | /// Returns a buffer containing a netlink message which requests a list of all the netfilter 74 | /// tables that are currently set. 75 | pub fn get_tables_nlmsg(seq: u32) -> Vec { 76 | let mut buffer = vec![0; crate::nft_nlmsg_maxsize() as usize]; 77 | let _ = unsafe { 78 | sys::nftnl_nlmsg_build_hdr( 79 | buffer.as_mut_ptr() as *mut c_char, 80 | libc::NFT_MSG_GETTABLE as u16, 81 | ProtoFamily::Unspec as u16, 82 | (libc::NLM_F_ROOT | libc::NLM_F_MATCH) as u16, 83 | seq, 84 | ) 85 | }; 86 | buffer 87 | } 88 | 89 | /// A callback to parse the response for messages created with `get_tables_nlmsg`. This callback 90 | /// extracts a set of applied table names. 91 | pub fn get_tables_cb(header: &libc::nlmsghdr, tables: &mut HashSet) -> libc::c_int { 92 | unsafe { 93 | let nf_table = sys::nftnl_table_alloc(); 94 | let err = sys::nftnl_table_nlmsg_parse(header, nf_table); 95 | if err < 0 { 96 | error!("Failed to parse nelink table message - {}", err); 97 | sys::nftnl_table_free(nf_table); 98 | return err; 99 | } 100 | let table_name = CStr::from_ptr(sys::nftnl_table_get_str( 101 | nf_table, 102 | sys::NFTNL_TABLE_NAME as u16, 103 | )) 104 | .to_owned(); 105 | tables.insert(table_name); 106 | sys::nftnl_table_free(nf_table); 107 | }; 108 | 1 109 | } 110 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Activation of features, almost objectively better ;) 2 | use_try_shorthand = true 3 | use_field_init_shorthand = true 4 | 5 | --------------------------------------------------------------------------------