From 05fda54da20d6c013a877028dd636d5af01979f3 Mon Sep 17 00:00:00 2001 From: Vibe Myass Date: Wed, 11 Mar 2026 01:40:27 +0000 Subject: [PATCH] Add src files --- LibNftables.slnx | 9 + README.md | 59 ++ docs/low-level-bindings-reference.md | 90 +++ eng/build-native.sh | 28 + eng/regen-bindings.sh | 22 + .../Generated/SWIGTYPE_p_nft_ctx.cs | 33 + .../Generated/libnftables.cs | 148 ++++ .../Generated/libnftablesPINVOKE.cs | 349 ++++++++ .../Generated/libnftables_wrap.c | 759 ++++++++++++++++++ .../Generated/nft_debug_level.cs | 23 + .../Generated/nft_optimize_flags.cs | 17 + .../LibNftables.Bindings.csproj | 31 + .../NativeLibraryBootstrap.cs | 53 ++ .../native/libLibNftablesBindings.so | Bin 0 -> 24664 bytes src/LibNftables.Bindings/swig/libnftables.i | 13 + src/LibNftables/INftablesClient.cs | 103 +++ src/LibNftables/LibNftables.csproj | 15 + src/LibNftables/NftApplyRequest.cs | 62 ++ src/LibNftables/NftContext.cs | 219 +++++ src/LibNftables/NftDerivedExceptions.cs | 68 ++ src/LibNftables/NftEnums.cs | 112 +++ src/LibNftables/NftErrorTranslator.cs | 47 ++ src/LibNftables/NftException.cs | 33 + src/LibNftables/NftRuntimeGuard.cs | 63 ++ src/LibNftables/NftSnapshot.cs | 8 + src/LibNftables/NftValidationResult.cs | 9 + src/LibNftables/NftablesClient.cs | 179 +++++ src/LibNftables/NftablesClientOptions.cs | 42 + .../LibNftables.Tests.csproj | 25 + tests/LibNftables.Tests/NftContextTests.cs | 142 ++++ tests/LibNftables.Tests/NftEnumTests.cs | 25 + .../LibNftables.Tests/NftablesClientTests.cs | 66 ++ 32 files changed, 2852 insertions(+) create mode 100644 LibNftables.slnx create mode 100644 README.md create mode 100644 docs/low-level-bindings-reference.md create mode 100755 eng/build-native.sh create mode 100755 eng/regen-bindings.sh create mode 100644 src/LibNftables.Bindings/Generated/SWIGTYPE_p_nft_ctx.cs create mode 100644 src/LibNftables.Bindings/Generated/libnftables.cs create mode 100644 src/LibNftables.Bindings/Generated/libnftablesPINVOKE.cs create mode 100644 src/LibNftables.Bindings/Generated/libnftables_wrap.c create mode 100644 src/LibNftables.Bindings/Generated/nft_debug_level.cs create mode 100644 src/LibNftables.Bindings/Generated/nft_optimize_flags.cs create mode 100644 src/LibNftables.Bindings/LibNftables.Bindings.csproj create mode 100644 src/LibNftables.Bindings/NativeLibraryBootstrap.cs create mode 100755 src/LibNftables.Bindings/runtimes/linux-x64/native/libLibNftablesBindings.so create mode 100644 src/LibNftables.Bindings/swig/libnftables.i create mode 100644 src/LibNftables/INftablesClient.cs create mode 100644 src/LibNftables/LibNftables.csproj create mode 100644 src/LibNftables/NftApplyRequest.cs create mode 100644 src/LibNftables/NftContext.cs create mode 100644 src/LibNftables/NftDerivedExceptions.cs create mode 100644 src/LibNftables/NftEnums.cs create mode 100644 src/LibNftables/NftErrorTranslator.cs create mode 100644 src/LibNftables/NftException.cs create mode 100644 src/LibNftables/NftRuntimeGuard.cs create mode 100644 src/LibNftables/NftSnapshot.cs create mode 100644 src/LibNftables/NftValidationResult.cs create mode 100644 src/LibNftables/NftablesClient.cs create mode 100644 src/LibNftables/NftablesClientOptions.cs create mode 100644 tests/LibNftables.Tests/LibNftables.Tests.csproj create mode 100644 tests/LibNftables.Tests/NftContextTests.cs create mode 100644 tests/LibNftables.Tests/NftEnumTests.cs create mode 100644 tests/LibNftables.Tests/NftablesClientTests.cs diff --git a/LibNftables.slnx b/LibNftables.slnx new file mode 100644 index 0000000..a6e7567 --- /dev/null +++ b/LibNftables.slnx @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cf1c48 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# libnftables-dotnet + +.NET bindings for system-installed `libnftables`, generated with SWIG. + +## Requirements + +- Linux +- `libnftables` headers and shared library installed +- `gcc` +- .NET SDK 10+ +- `swig` (only needed to regenerate bindings) + +## Build + +```bash +dotnet build +``` + +`dotnet build` compiles the native SWIG wrapper (`libLibNftablesBindings.so`) from checked-in generated C wrapper code. + +## Regenerate SWIG bindings + +```bash +./eng/regen-bindings.sh +``` + +## Native wrapper build only + +```bash +./eng/build-native.sh +``` + +## Notes + +- Native dependency remains system-level `libnftables` (`-lnftables`). +- Managed APIs: + - `NftContext`: advanced low-level context wrapper over native calls. + - `INftablesClient` / `NftablesClient`: high-level command-centric API with `Validate`, `Apply`, `Snapshot`, and `Restore` (sync + async). +- Fail-fast runtime policy: Linux x64 only for native operations. + +## Documentation + +- High-level managed API XML docs are provided on all public `LibNftables` types/members. +- Low-level generated binding reference: `docs/low-level-bindings-reference.md`. +- Generated SWIG files under `src/LibNftables.Bindings/Generated/` are auto-generated and not hand-edited. + +## High-level example + +```csharp +using LibNftables; + +INftablesClient client = new NftablesClient(); + +var validation = client.Validate(NftApplyRequest.FromText("add table inet my_table")); +if (validation.IsValid) +{ + client.Apply(NftApplyRequest.FromText("add table inet my_table")); +} +``` diff --git a/docs/low-level-bindings-reference.md b/docs/low-level-bindings-reference.md new file mode 100644 index 0000000..30c6e94 --- /dev/null +++ b/docs/low-level-bindings-reference.md @@ -0,0 +1,90 @@ +# Low-Level Binding Reference (`LibNftables.Bindings.Generated`) + +This document describes the generated low-level .NET bindings for `libnftables`. + +## Generation policy + +- Source of truth: `/usr/include/nftables/libnftables.h` +- Generator: SWIG C# (`./eng/regen-bindings.sh`) +- Generated files are under `src/LibNftables.Bindings/Generated/`. +- Do not manually edit generated files. Regenerate instead. + +## Primary generated types + +- `libnftables`: static entrypoint for native calls and exported constants. +- `SWIGTYPE_p_nft_ctx`: opaque native context pointer wrapper. +- `nft_debug_level`: generated native debug enum. +- `nft_optimize_flags`: generated native optimize enum. + +## API groups + +### 1) Context lifecycle + +- `nft_ctx_new(uint flags)` +- `nft_ctx_free(SWIGTYPE_p_nft_ctx ctx)` + +These allocate/free the native `nft_ctx` handle. + +### 2) Context behavior flags + +- Dry-run: + - `nft_ctx_get_dry_run(...)` + - `nft_ctx_set_dry_run(...)` +- Optimize: + - `nft_ctx_get_optimize(...)` + - `nft_ctx_set_optimize(...)` +- Input flags: + - `nft_ctx_input_get_flags(...)` + - `nft_ctx_input_set_flags(...)` +- Output flags: + - `nft_ctx_output_get_flags(...)` + - `nft_ctx_output_set_flags(...)` +- Debug flags: + - `nft_ctx_output_get_debug(...)` + - `nft_ctx_output_set_debug(...)` + +### 3) Buffered output/error capture + +- Output buffer: + - `nft_ctx_buffer_output(...)` + - `nft_ctx_unbuffer_output(...)` + - `nft_ctx_get_output_buffer(...)` +- Error buffer: + - `nft_ctx_buffer_error(...)` + - `nft_ctx_unbuffer_error(...)` + - `nft_ctx_get_error_buffer(...)` + +### 4) Include paths and variables + +- Include paths: + - `nft_ctx_add_include_path(...)` + - `nft_ctx_clear_include_paths(...)` +- Variables: + - `nft_ctx_add_var(...)` + - `nft_ctx_clear_vars(...)` + +### 5) Command execution + +- `nft_run_cmd_from_buffer(...)` +- `nft_run_cmd_from_filename(...)` + +These are the low-level command execution entrypoints. + +## Constants exposed via generated class + +`libnftables` exposes native constants as static readonly fields, including: + +- `NFT_CTX_DEFAULT` +- `NFT_CTX_INPUT_*` +- `NFT_CTX_OUTPUT_*` + +Use the high-level enums in `LibNftables` when possible. + +## Relation to high-level API + +Use low-level generated bindings only when you need direct native semantics. + +For application code, prefer: + +- `NftablesClient` / `INftablesClient` for workflow operations (validate/apply/snapshot/restore) +- `NftContext` for advanced managed control over native context settings diff --git a/eng/build-native.sh b/eng/build-native.sh new file mode 100755 index 0000000..95a3fb2 --- /dev/null +++ b/eng/build-native.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BINDINGS_DIR="$ROOT_DIR/src/LibNftables.Bindings" +WRAP_FILE="$BINDINGS_DIR/Generated/libnftables_wrap.c" +OUT_DIR="$BINDINGS_DIR/runtimes/linux-x64/native" +OUT_FILE="$OUT_DIR/libLibNftablesBindings.so" + +if [[ ! -f "$WRAP_FILE" ]]; then + echo "Missing SWIG wrapper: $WRAP_FILE" >&2 + echo "Run ./eng/regen-bindings.sh first." >&2 + exit 1 +fi + +mkdir -p "$OUT_DIR" + +CFLAGS="$(pkg-config --cflags libnftables 2>/dev/null || true)" +LIBS="$(pkg-config --libs libnftables 2>/dev/null || echo '-lnftables')" + +gcc -fPIC -shared -O2 \ + $CFLAGS \ + -I/usr/include \ + "$WRAP_FILE" \ + -o "$OUT_FILE" \ + $LIBS + +echo "Built native wrapper: $OUT_FILE" diff --git a/eng/regen-bindings.sh b/eng/regen-bindings.sh new file mode 100755 index 0000000..9fac653 --- /dev/null +++ b/eng/regen-bindings.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BINDINGS_DIR="$ROOT_DIR/src/LibNftables.Bindings" +SWIG_FILE="$BINDINGS_DIR/swig/libnftables.i" +OUT_DIR="$BINDINGS_DIR/Generated" + +mkdir -p "$OUT_DIR" +rm -f "$OUT_DIR"/*.cs "$OUT_DIR"/*_wrap.c + +swig \ + -csharp \ + -I/usr/include \ + -I/usr/local/include \ + -namespace LibNftables.Bindings.Native \ + -dllimport LibNftablesBindings \ + -outdir "$OUT_DIR" \ + -o "$OUT_DIR/libnftables_wrap.c" \ + "$SWIG_FILE" + +echo "Generated SWIG bindings in $OUT_DIR" diff --git a/src/LibNftables.Bindings/Generated/SWIGTYPE_p_nft_ctx.cs b/src/LibNftables.Bindings/Generated/SWIGTYPE_p_nft_ctx.cs new file mode 100644 index 0000000..92f03bc --- /dev/null +++ b/src/LibNftables.Bindings/Generated/SWIGTYPE_p_nft_ctx.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (https://www.swig.org). +// Version 4.3.0 +// +// Do not make changes to this file unless you know what you are doing - modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace LibNftables.Bindings.Native { + +public class SWIGTYPE_p_nft_ctx { + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + + internal SWIGTYPE_p_nft_ctx(global::System.IntPtr cPtr, bool futureUse) { + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_nft_ctx() { + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(SWIGTYPE_p_nft_ctx obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + internal static global::System.Runtime.InteropServices.HandleRef swigRelease(SWIGTYPE_p_nft_ctx obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } +} + +} diff --git a/src/LibNftables.Bindings/Generated/libnftables.cs b/src/LibNftables.Bindings/Generated/libnftables.cs new file mode 100644 index 0000000..4b3d211 --- /dev/null +++ b/src/LibNftables.Bindings/Generated/libnftables.cs @@ -0,0 +1,148 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (https://www.swig.org). +// Version 4.3.0 +// +// Do not make changes to this file unless you know what you are doing - modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace LibNftables.Bindings.Native { + +public class libnftables { + public static SWIGTYPE_p_nft_ctx nft_ctx_new(uint flags) { + global::System.IntPtr cPtr = libnftablesPINVOKE.nft_ctx_new(flags); + SWIGTYPE_p_nft_ctx ret = (cPtr == global::System.IntPtr.Zero) ? null : new SWIGTYPE_p_nft_ctx(cPtr, false); + return ret; + } + + public static void nft_ctx_free(SWIGTYPE_p_nft_ctx ctx) { + libnftablesPINVOKE.nft_ctx_free(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + } + + public static bool nft_ctx_get_dry_run(SWIGTYPE_p_nft_ctx ctx) { + bool ret = libnftablesPINVOKE.nft_ctx_get_dry_run(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static void nft_ctx_set_dry_run(SWIGTYPE_p_nft_ctx ctx, bool dry) { + libnftablesPINVOKE.nft_ctx_set_dry_run(SWIGTYPE_p_nft_ctx.getCPtr(ctx), dry); + } + + public static uint nft_ctx_get_optimize(SWIGTYPE_p_nft_ctx ctx) { + uint ret = libnftablesPINVOKE.nft_ctx_get_optimize(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static void nft_ctx_set_optimize(SWIGTYPE_p_nft_ctx ctx, uint flags) { + libnftablesPINVOKE.nft_ctx_set_optimize(SWIGTYPE_p_nft_ctx.getCPtr(ctx), flags); + } + + public static uint nft_ctx_input_get_flags(SWIGTYPE_p_nft_ctx ctx) { + uint ret = libnftablesPINVOKE.nft_ctx_input_get_flags(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static uint nft_ctx_input_set_flags(SWIGTYPE_p_nft_ctx ctx, uint flags) { + uint ret = libnftablesPINVOKE.nft_ctx_input_set_flags(SWIGTYPE_p_nft_ctx.getCPtr(ctx), flags); + return ret; + } + + public static uint nft_ctx_output_get_flags(SWIGTYPE_p_nft_ctx ctx) { + uint ret = libnftablesPINVOKE.nft_ctx_output_get_flags(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static void nft_ctx_output_set_flags(SWIGTYPE_p_nft_ctx ctx, uint flags) { + libnftablesPINVOKE.nft_ctx_output_set_flags(SWIGTYPE_p_nft_ctx.getCPtr(ctx), flags); + } + + public static uint nft_ctx_output_get_debug(SWIGTYPE_p_nft_ctx ctx) { + uint ret = libnftablesPINVOKE.nft_ctx_output_get_debug(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static void nft_ctx_output_set_debug(SWIGTYPE_p_nft_ctx ctx, uint mask) { + libnftablesPINVOKE.nft_ctx_output_set_debug(SWIGTYPE_p_nft_ctx.getCPtr(ctx), mask); + } + + public static int nft_ctx_buffer_output(SWIGTYPE_p_nft_ctx ctx) { + int ret = libnftablesPINVOKE.nft_ctx_buffer_output(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static int nft_ctx_unbuffer_output(SWIGTYPE_p_nft_ctx ctx) { + int ret = libnftablesPINVOKE.nft_ctx_unbuffer_output(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static string nft_ctx_get_output_buffer(SWIGTYPE_p_nft_ctx ctx) { + string ret = libnftablesPINVOKE.nft_ctx_get_output_buffer(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static int nft_ctx_buffer_error(SWIGTYPE_p_nft_ctx ctx) { + int ret = libnftablesPINVOKE.nft_ctx_buffer_error(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static int nft_ctx_unbuffer_error(SWIGTYPE_p_nft_ctx ctx) { + int ret = libnftablesPINVOKE.nft_ctx_unbuffer_error(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static string nft_ctx_get_error_buffer(SWIGTYPE_p_nft_ctx ctx) { + string ret = libnftablesPINVOKE.nft_ctx_get_error_buffer(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + return ret; + } + + public static int nft_ctx_add_include_path(SWIGTYPE_p_nft_ctx ctx, string path) { + int ret = libnftablesPINVOKE.nft_ctx_add_include_path(SWIGTYPE_p_nft_ctx.getCPtr(ctx), path); + return ret; + } + + public static void nft_ctx_clear_include_paths(SWIGTYPE_p_nft_ctx ctx) { + libnftablesPINVOKE.nft_ctx_clear_include_paths(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + } + + public static int nft_ctx_add_var(SWIGTYPE_p_nft_ctx ctx, string var) { + int ret = libnftablesPINVOKE.nft_ctx_add_var(SWIGTYPE_p_nft_ctx.getCPtr(ctx), var); + return ret; + } + + public static void nft_ctx_clear_vars(SWIGTYPE_p_nft_ctx ctx) { + libnftablesPINVOKE.nft_ctx_clear_vars(SWIGTYPE_p_nft_ctx.getCPtr(ctx)); + } + + public static int nft_run_cmd_from_buffer(SWIGTYPE_p_nft_ctx nft, string buf) { + int ret = libnftablesPINVOKE.nft_run_cmd_from_buffer(SWIGTYPE_p_nft_ctx.getCPtr(nft), buf); + return ret; + } + + public static int nft_run_cmd_from_filename(SWIGTYPE_p_nft_ctx nft, string filename) { + int ret = libnftablesPINVOKE.nft_run_cmd_from_filename(SWIGTYPE_p_nft_ctx.getCPtr(nft), filename); + return ret; + } + + public static readonly int NFT_CTX_DEFAULT = libnftablesPINVOKE.NFT_CTX_DEFAULT_get(); + public static readonly int NFT_CTX_INPUT_NO_DNS = libnftablesPINVOKE.NFT_CTX_INPUT_NO_DNS_get(); + public static readonly int NFT_CTX_INPUT_JSON = libnftablesPINVOKE.NFT_CTX_INPUT_JSON_get(); + + public static readonly int NFT_CTX_OUTPUT_REVERSEDNS = libnftablesPINVOKE.NFT_CTX_OUTPUT_REVERSEDNS_get(); + public static readonly int NFT_CTX_OUTPUT_SERVICE = libnftablesPINVOKE.NFT_CTX_OUTPUT_SERVICE_get(); + public static readonly int NFT_CTX_OUTPUT_STATELESS = libnftablesPINVOKE.NFT_CTX_OUTPUT_STATELESS_get(); + public static readonly int NFT_CTX_OUTPUT_HANDLE = libnftablesPINVOKE.NFT_CTX_OUTPUT_HANDLE_get(); + public static readonly int NFT_CTX_OUTPUT_JSON = libnftablesPINVOKE.NFT_CTX_OUTPUT_JSON_get(); + public static readonly int NFT_CTX_OUTPUT_ECHO = libnftablesPINVOKE.NFT_CTX_OUTPUT_ECHO_get(); + public static readonly int NFT_CTX_OUTPUT_GUID = libnftablesPINVOKE.NFT_CTX_OUTPUT_GUID_get(); + public static readonly int NFT_CTX_OUTPUT_NUMERIC_PROTO = libnftablesPINVOKE.NFT_CTX_OUTPUT_NUMERIC_PROTO_get(); + public static readonly int NFT_CTX_OUTPUT_NUMERIC_PRIO = libnftablesPINVOKE.NFT_CTX_OUTPUT_NUMERIC_PRIO_get(); + public static readonly int NFT_CTX_OUTPUT_NUMERIC_SYMBOL = libnftablesPINVOKE.NFT_CTX_OUTPUT_NUMERIC_SYMBOL_get(); + public static readonly int NFT_CTX_OUTPUT_NUMERIC_TIME = libnftablesPINVOKE.NFT_CTX_OUTPUT_NUMERIC_TIME_get(); + public static readonly int NFT_CTX_OUTPUT_NUMERIC_ALL = libnftablesPINVOKE.NFT_CTX_OUTPUT_NUMERIC_ALL_get(); + public static readonly int NFT_CTX_OUTPUT_TERSE = libnftablesPINVOKE.NFT_CTX_OUTPUT_TERSE_get(); + +} + +} diff --git a/src/LibNftables.Bindings/Generated/libnftablesPINVOKE.cs b/src/LibNftables.Bindings/Generated/libnftablesPINVOKE.cs new file mode 100644 index 0000000..65cbe5a --- /dev/null +++ b/src/LibNftables.Bindings/Generated/libnftablesPINVOKE.cs @@ -0,0 +1,349 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (https://www.swig.org). +// Version 4.3.0 +// +// Do not make changes to this file unless you know what you are doing - modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace LibNftables.Bindings.Native { + +class libnftablesPINVOKE { + + protected class SWIGExceptionHelper { + + public delegate void ExceptionDelegate(string message); + public delegate void ExceptionArgumentDelegate(string message, string paramName); + + static ExceptionDelegate applicationDelegate = new ExceptionDelegate(SetPendingApplicationException); + static ExceptionDelegate arithmeticDelegate = new ExceptionDelegate(SetPendingArithmeticException); + static ExceptionDelegate divideByZeroDelegate = new ExceptionDelegate(SetPendingDivideByZeroException); + static ExceptionDelegate indexOutOfRangeDelegate = new ExceptionDelegate(SetPendingIndexOutOfRangeException); + static ExceptionDelegate invalidCastDelegate = new ExceptionDelegate(SetPendingInvalidCastException); + static ExceptionDelegate invalidOperationDelegate = new ExceptionDelegate(SetPendingInvalidOperationException); + static ExceptionDelegate ioDelegate = new ExceptionDelegate(SetPendingIOException); + static ExceptionDelegate nullReferenceDelegate = new ExceptionDelegate(SetPendingNullReferenceException); + static ExceptionDelegate outOfMemoryDelegate = new ExceptionDelegate(SetPendingOutOfMemoryException); + static ExceptionDelegate overflowDelegate = new ExceptionDelegate(SetPendingOverflowException); + static ExceptionDelegate systemDelegate = new ExceptionDelegate(SetPendingSystemException); + + static ExceptionArgumentDelegate argumentDelegate = new ExceptionArgumentDelegate(SetPendingArgumentException); + static ExceptionArgumentDelegate argumentNullDelegate = new ExceptionArgumentDelegate(SetPendingArgumentNullException); + static ExceptionArgumentDelegate argumentOutOfRangeDelegate = new ExceptionArgumentDelegate(SetPendingArgumentOutOfRangeException); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="SWIGRegisterExceptionCallbacks_libnftables")] + public static extern void SWIGRegisterExceptionCallbacks_libnftables( + ExceptionDelegate applicationDelegate, + ExceptionDelegate arithmeticDelegate, + ExceptionDelegate divideByZeroDelegate, + ExceptionDelegate indexOutOfRangeDelegate, + ExceptionDelegate invalidCastDelegate, + ExceptionDelegate invalidOperationDelegate, + ExceptionDelegate ioDelegate, + ExceptionDelegate nullReferenceDelegate, + ExceptionDelegate outOfMemoryDelegate, + ExceptionDelegate overflowDelegate, + ExceptionDelegate systemExceptionDelegate); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="SWIGRegisterExceptionArgumentCallbacks_libnftables")] + public static extern void SWIGRegisterExceptionCallbacksArgument_libnftables( + ExceptionArgumentDelegate argumentDelegate, + ExceptionArgumentDelegate argumentNullDelegate, + ExceptionArgumentDelegate argumentOutOfRangeDelegate); + + static void SetPendingApplicationException(string message) { + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingArithmeticException(string message) { + SWIGPendingException.Set(new global::System.ArithmeticException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingDivideByZeroException(string message) { + SWIGPendingException.Set(new global::System.DivideByZeroException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingIndexOutOfRangeException(string message) { + SWIGPendingException.Set(new global::System.IndexOutOfRangeException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingInvalidCastException(string message) { + SWIGPendingException.Set(new global::System.InvalidCastException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingInvalidOperationException(string message) { + SWIGPendingException.Set(new global::System.InvalidOperationException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingIOException(string message) { + SWIGPendingException.Set(new global::System.IO.IOException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingNullReferenceException(string message) { + SWIGPendingException.Set(new global::System.NullReferenceException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingOutOfMemoryException(string message) { + SWIGPendingException.Set(new global::System.OutOfMemoryException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingOverflowException(string message) { + SWIGPendingException.Set(new global::System.OverflowException(message, SWIGPendingException.Retrieve())); + } + static void SetPendingSystemException(string message) { + SWIGPendingException.Set(new global::System.SystemException(message, SWIGPendingException.Retrieve())); + } + + static void SetPendingArgumentException(string message, string paramName) { + SWIGPendingException.Set(new global::System.ArgumentException(message, paramName, SWIGPendingException.Retrieve())); + } + static void SetPendingArgumentNullException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentNullException(paramName, message)); + } + static void SetPendingArgumentOutOfRangeException(string message, string paramName) { + global::System.Exception e = SWIGPendingException.Retrieve(); + if (e != null) message = message + " Inner Exception: " + e.Message; + SWIGPendingException.Set(new global::System.ArgumentOutOfRangeException(paramName, message)); + } + + static SWIGExceptionHelper() { + SWIGRegisterExceptionCallbacks_libnftables( + applicationDelegate, + arithmeticDelegate, + divideByZeroDelegate, + indexOutOfRangeDelegate, + invalidCastDelegate, + invalidOperationDelegate, + ioDelegate, + nullReferenceDelegate, + outOfMemoryDelegate, + overflowDelegate, + systemDelegate); + + SWIGRegisterExceptionCallbacksArgument_libnftables( + argumentDelegate, + argumentNullDelegate, + argumentOutOfRangeDelegate); + } + } + + protected static SWIGExceptionHelper swigExceptionHelper = new SWIGExceptionHelper(); + + public class SWIGPendingException { + [global::System.ThreadStatic] + private static global::System.Exception pendingException = null; + private static int numExceptionsPending = 0; + private static global::System.Object exceptionsLock = null; + + public static bool Pending { + get { + bool pending = false; + if (numExceptionsPending > 0) + if (pendingException != null) + pending = true; + return pending; + } + } + + public static void Set(global::System.Exception e) { + if (pendingException != null) + throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); + pendingException = e; + lock(exceptionsLock) { + numExceptionsPending++; + } + } + + public static global::System.Exception Retrieve() { + global::System.Exception e = null; + if (numExceptionsPending > 0) { + if (pendingException != null) { + e = pendingException; + pendingException = null; + lock(exceptionsLock) { + numExceptionsPending--; + } + } + } + return e; + } + + static SWIGPendingException() { + exceptionsLock = new global::System.Object(); + } + } + + + protected class SWIGStringHelper { + + public delegate string SWIGStringDelegate(string message); + static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="SWIGRegisterStringCallback_libnftables")] + public static extern void SWIGRegisterStringCallback_libnftables(SWIGStringDelegate stringDelegate); + + static string CreateString(string cString) { + return cString; + } + + static SWIGStringHelper() { + SWIGRegisterStringCallback_libnftables(stringDelegate); + } + } + + static protected SWIGStringHelper swigStringHelper = new SWIGStringHelper(); + + + public class SWIGStringWithLengthHelper { + + [global::System.Runtime.InteropServices.DllImport("libnftables", EntryPoint="SWIG_csharp_string_to_c")] + private static extern global::System.IntPtr SWIG_csharp_string_to_c0(int size, int len, [global::System.Runtime.InteropServices.In,global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPStr, SizeParamIndex=0)] string str); + + [global::System.Runtime.InteropServices.DllImport("libnftables", EntryPoint="SWIG_csharp_string_size")] + private static extern int SWIG_csharp_string_size(global::System.IntPtr str); + + [global::System.Runtime.InteropServices.DllImport("libnftables", EntryPoint="SWIG_csharp_string_str")] + private static extern global::System.IntPtr SWIG_csharp_string_str(global::System.IntPtr str); + + public static global::System.IntPtr SWIG_csharp_string_to_c(string str) { + if (str == null) + return global::System.IntPtr.Zero; + global::System.Text.Encoding utf8 = global::System.Text.Encoding.UTF8; + return SWIG_csharp_string_to_c0(utf8.GetByteCount(str), str.Length, str); + } + + public static string SWIG_c_to_csharp_string(global::System.IntPtr str) { + int size = SWIG_csharp_string_size(str); + if (size > 0) { + global::System.IntPtr s = SWIG_csharp_string_str(str); + byte[] b = new byte[size]; + global::System.Runtime.InteropServices.Marshal.Copy(s, b, 0, size); + global::System.Text.Encoding utf8 = global::System.Text.Encoding.UTF8; + return utf8.GetString(b); + } + return null; + } + } + + + static libnftablesPINVOKE() { + } + + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_DEFAULT_get___")] + public static extern int NFT_CTX_DEFAULT_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_new___")] + public static extern global::System.IntPtr nft_ctx_new(uint jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_free___")] + public static extern void nft_ctx_free(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_get_dry_run___")] + public static extern bool nft_ctx_get_dry_run(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_set_dry_run___")] + public static extern void nft_ctx_set_dry_run(global::System.Runtime.InteropServices.HandleRef jarg1, bool jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_get_optimize___")] + public static extern uint nft_ctx_get_optimize(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_set_optimize___")] + public static extern void nft_ctx_set_optimize(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_INPUT_NO_DNS_get___")] + public static extern int NFT_CTX_INPUT_NO_DNS_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_INPUT_JSON_get___")] + public static extern int NFT_CTX_INPUT_JSON_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_input_get_flags___")] + public static extern uint nft_ctx_input_get_flags(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_input_set_flags___")] + public static extern uint nft_ctx_input_set_flags(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_REVERSEDNS_get___")] + public static extern int NFT_CTX_OUTPUT_REVERSEDNS_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_SERVICE_get___")] + public static extern int NFT_CTX_OUTPUT_SERVICE_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_STATELESS_get___")] + public static extern int NFT_CTX_OUTPUT_STATELESS_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_HANDLE_get___")] + public static extern int NFT_CTX_OUTPUT_HANDLE_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_JSON_get___")] + public static extern int NFT_CTX_OUTPUT_JSON_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_ECHO_get___")] + public static extern int NFT_CTX_OUTPUT_ECHO_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_GUID_get___")] + public static extern int NFT_CTX_OUTPUT_GUID_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_PROTO_get___")] + public static extern int NFT_CTX_OUTPUT_NUMERIC_PROTO_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_PRIO_get___")] + public static extern int NFT_CTX_OUTPUT_NUMERIC_PRIO_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_SYMBOL_get___")] + public static extern int NFT_CTX_OUTPUT_NUMERIC_SYMBOL_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_TIME_get___")] + public static extern int NFT_CTX_OUTPUT_NUMERIC_TIME_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_ALL_get___")] + public static extern int NFT_CTX_OUTPUT_NUMERIC_ALL_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_TERSE_get___")] + public static extern int NFT_CTX_OUTPUT_TERSE_get(); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_output_get_flags___")] + public static extern uint nft_ctx_output_get_flags(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_output_set_flags___")] + public static extern void nft_ctx_output_set_flags(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_output_get_debug___")] + public static extern uint nft_ctx_output_get_debug(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_output_set_debug___")] + public static extern void nft_ctx_output_set_debug(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_buffer_output___")] + public static extern int nft_ctx_buffer_output(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_unbuffer_output___")] + public static extern int nft_ctx_unbuffer_output(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_get_output_buffer___")] + public static extern string nft_ctx_get_output_buffer(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_buffer_error___")] + public static extern int nft_ctx_buffer_error(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_unbuffer_error___")] + public static extern int nft_ctx_unbuffer_error(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_get_error_buffer___")] + public static extern string nft_ctx_get_error_buffer(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_add_include_path___")] + public static extern int nft_ctx_add_include_path(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_clear_include_paths___")] + public static extern void nft_ctx_clear_include_paths(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_add_var___")] + public static extern int nft_ctx_add_var(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_ctx_clear_vars___")] + public static extern void nft_ctx_clear_vars(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_run_cmd_from_buffer___")] + public static extern int nft_run_cmd_from_buffer(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2); + + [global::System.Runtime.InteropServices.DllImport("LibNftablesBindings", EntryPoint="CSharp_LibNftablesfBindingsfNative_nft_run_cmd_from_filename___")] + public static extern int nft_run_cmd_from_filename(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2); +} + +} diff --git a/src/LibNftables.Bindings/Generated/libnftables_wrap.c b/src/LibNftables.Bindings/Generated/libnftables_wrap.c new file mode 100644 index 0000000..744e950 --- /dev/null +++ b/src/LibNftables.Bindings/Generated/libnftables_wrap.c @@ -0,0 +1,759 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (https://www.swig.org). + * Version 4.3.0 + * + * Do not make changes to this file unless you know what you are doing - modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + + +#define SWIG_VERSION 0x040300 +#define SWIGCSHARP + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + +#if defined(__cplusplus) && __cplusplus >=201103L +# define SWIG_NULLPTR nullptr +#else +# define SWIG_NULLPTR NULL +#endif + +/* ----------------------------------------------------------------------------- + * swigcompat.swg + * + * Macros to provide support compatibility with older C and C++ standards. + * + * Note that SWIG expects __cplusplus to be defined to the appropriate C++ standard. + * MSVC users are urged to check and examine the /Zc:__cplusplus compiler option. + * See https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus. + * ----------------------------------------------------------------------------- */ + +/* C99 and C++11 should provide snprintf, but define SWIG_NO_SNPRINTF + * if you're missing it. + */ +#if ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || \ + (defined __cplusplus && __cplusplus >= 201103L) || \ + defined SWIG_HAVE_SNPRINTF) && \ + !defined SWIG_NO_SNPRINTF +# define SWIG_snprintf(O,S,F,A) snprintf(O,S,F,A) +# define SWIG_snprintf2(O,S,F,A,B) snprintf(O,S,F,A,B) +#else +/* Fallback versions ignore the buffer size, but most of our uses either have a + * fixed maximum possible size or dynamically allocate a buffer that's large + * enough. + */ +# define SWIG_snprintf(O,S,F,A) sprintf(O,F,A) +# define SWIG_snprintf2(O,S,F,A,B) sprintf(O,F,A,B) +#endif + + +#include +#include +#include + + +/* Support for throwing C# exceptions from C/C++. There are two types: + * Exceptions that take a message and ArgumentExceptions that take a message and a parameter name. */ +typedef enum { + SWIG_CSharpApplicationException, + SWIG_CSharpArithmeticException, + SWIG_CSharpDivideByZeroException, + SWIG_CSharpIndexOutOfRangeException, + SWIG_CSharpInvalidCastException, + SWIG_CSharpInvalidOperationException, + SWIG_CSharpIOException, + SWIG_CSharpNullReferenceException, + SWIG_CSharpOutOfMemoryException, + SWIG_CSharpOverflowException, + SWIG_CSharpSystemException +} SWIG_CSharpExceptionCodes; + +typedef enum { + SWIG_CSharpArgumentException, + SWIG_CSharpArgumentNullException, + SWIG_CSharpArgumentOutOfRangeException +} SWIG_CSharpExceptionArgumentCodes; + +typedef void (SWIGSTDCALL* SWIG_CSharpExceptionCallback_t)(const char *); +typedef void (SWIGSTDCALL* SWIG_CSharpExceptionArgumentCallback_t)(const char *, const char *); + +typedef struct { + SWIG_CSharpExceptionCodes code; + SWIG_CSharpExceptionCallback_t callback; +} SWIG_CSharpException_t; + +typedef struct { + SWIG_CSharpExceptionArgumentCodes code; + SWIG_CSharpExceptionArgumentCallback_t callback; +} SWIG_CSharpExceptionArgument_t; + +static SWIG_CSharpException_t SWIG_csharp_exceptions[] = { + { SWIG_CSharpApplicationException, NULL }, + { SWIG_CSharpArithmeticException, NULL }, + { SWIG_CSharpDivideByZeroException, NULL }, + { SWIG_CSharpIndexOutOfRangeException, NULL }, + { SWIG_CSharpInvalidCastException, NULL }, + { SWIG_CSharpInvalidOperationException, NULL }, + { SWIG_CSharpIOException, NULL }, + { SWIG_CSharpNullReferenceException, NULL }, + { SWIG_CSharpOutOfMemoryException, NULL }, + { SWIG_CSharpOverflowException, NULL }, + { SWIG_CSharpSystemException, NULL } +}; + +static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = { + { SWIG_CSharpArgumentException, NULL }, + { SWIG_CSharpArgumentNullException, NULL }, + { SWIG_CSharpArgumentOutOfRangeException, NULL } +}; + +static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) { + SWIG_CSharpExceptionCallback_t callback = SWIG_csharp_exceptions[SWIG_CSharpApplicationException].callback; + if ((size_t)code < sizeof(SWIG_csharp_exceptions)/sizeof(SWIG_CSharpException_t)) { + callback = SWIG_csharp_exceptions[code].callback; + } + callback(msg); +} + +static void SWIGUNUSED SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpExceptionArgumentCodes code, const char *msg, const char *param_name) { + SWIG_CSharpExceptionArgumentCallback_t callback = SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentException].callback; + if ((size_t)code < sizeof(SWIG_csharp_exceptions_argument)/sizeof(SWIG_CSharpExceptionArgument_t)) { + callback = SWIG_csharp_exceptions_argument[code].callback; + } + callback(msg, param_name); +} + + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionCallbacks_libnftables( + SWIG_CSharpExceptionCallback_t applicationCallback, + SWIG_CSharpExceptionCallback_t arithmeticCallback, + SWIG_CSharpExceptionCallback_t divideByZeroCallback, + SWIG_CSharpExceptionCallback_t indexOutOfRangeCallback, + SWIG_CSharpExceptionCallback_t invalidCastCallback, + SWIG_CSharpExceptionCallback_t invalidOperationCallback, + SWIG_CSharpExceptionCallback_t ioCallback, + SWIG_CSharpExceptionCallback_t nullReferenceCallback, + SWIG_CSharpExceptionCallback_t outOfMemoryCallback, + SWIG_CSharpExceptionCallback_t overflowCallback, + SWIG_CSharpExceptionCallback_t systemCallback) { + SWIG_csharp_exceptions[SWIG_CSharpApplicationException].callback = applicationCallback; + SWIG_csharp_exceptions[SWIG_CSharpArithmeticException].callback = arithmeticCallback; + SWIG_csharp_exceptions[SWIG_CSharpDivideByZeroException].callback = divideByZeroCallback; + SWIG_csharp_exceptions[SWIG_CSharpIndexOutOfRangeException].callback = indexOutOfRangeCallback; + SWIG_csharp_exceptions[SWIG_CSharpInvalidCastException].callback = invalidCastCallback; + SWIG_csharp_exceptions[SWIG_CSharpInvalidOperationException].callback = invalidOperationCallback; + SWIG_csharp_exceptions[SWIG_CSharpIOException].callback = ioCallback; + SWIG_csharp_exceptions[SWIG_CSharpNullReferenceException].callback = nullReferenceCallback; + SWIG_csharp_exceptions[SWIG_CSharpOutOfMemoryException].callback = outOfMemoryCallback; + SWIG_csharp_exceptions[SWIG_CSharpOverflowException].callback = overflowCallback; + SWIG_csharp_exceptions[SWIG_CSharpSystemException].callback = systemCallback; +} + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_libnftables( + SWIG_CSharpExceptionArgumentCallback_t argumentCallback, + SWIG_CSharpExceptionArgumentCallback_t argumentNullCallback, + SWIG_CSharpExceptionArgumentCallback_t argumentOutOfRangeCallback) { + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentException].callback = argumentCallback; + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentNullException].callback = argumentNullCallback; + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentOutOfRangeException].callback = argumentOutOfRangeCallback; +} + + +/* Callback for returning strings to C# without leaking memory */ +typedef char * (SWIGSTDCALL* SWIG_CSharpStringHelperCallback)(const char *); +static SWIG_CSharpStringHelperCallback SWIG_csharp_string_callback = NULL; + + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterStringCallback_libnftables(SWIG_CSharpStringHelperCallback callback) { + SWIG_csharp_string_callback = callback; +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) do { if (!(expr)) {SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, msg, ""); return nullreturn; } } while (0) + + +#include + + +#include // Use the C99 official header + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_DEFAULT_get___() { + int jresult ; + int result; + + result = (int)(0); + jresult = result; + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_new___(unsigned int jarg1) { + void * jresult ; + uint32_t arg1 ; + struct nft_ctx *result = 0 ; + + arg1 = (uint32_t)jarg1; + result = (struct nft_ctx *)nft_ctx_new(arg1); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_free___(void * jarg1) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + + arg1 = (struct nft_ctx *)jarg1; + nft_ctx_free(arg1); +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_get_dry_run___(void * jarg1) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + bool result; + + arg1 = (struct nft_ctx *)jarg1; + result = (bool)nft_ctx_get_dry_run(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_set_dry_run___(void * jarg1, unsigned int jarg2) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + bool arg2 ; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = jarg2 ? true : false; + nft_ctx_set_dry_run(arg1,arg2); +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_get_optimize___(void * jarg1) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + uint32_t result; + + arg1 = (struct nft_ctx *)jarg1; + result = (uint32_t)nft_ctx_get_optimize(arg1); + jresult = (unsigned int)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_set_optimize___(void * jarg1, unsigned int jarg2) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + uint32_t arg2 ; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (uint32_t)jarg2; + nft_ctx_set_optimize(arg1,arg2); +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_INPUT_NO_DNS_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_INPUT_NO_DNS; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_INPUT_JSON_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_INPUT_JSON; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_input_get_flags___(void * jarg1) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (unsigned int)nft_ctx_input_get_flags(arg1); + jresult = (unsigned int)result; + return jresult; +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_input_set_flags___(void * jarg1, unsigned int jarg2) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int arg2 ; + unsigned int result; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (unsigned int)jarg2; + result = (unsigned int)nft_ctx_input_set_flags(arg1,arg2); + jresult = (unsigned int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_REVERSEDNS_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_REVERSEDNS; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_SERVICE_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_SERVICE; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_STATELESS_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_STATELESS; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_HANDLE_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_HANDLE; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_JSON_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_JSON; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_ECHO_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_ECHO; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_GUID_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_GUID; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_PROTO_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_NUMERIC_PROTO; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_PRIO_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_NUMERIC_PRIO; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_SYMBOL_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_NUMERIC_SYMBOL; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_TIME_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_NUMERIC_TIME; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_NUMERIC_ALL_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_NUMERIC_ALL; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_NFT_CTX_OUTPUT_TERSE_get___() { + int jresult ; + int result; + + result = (int)NFT_CTX_OUTPUT_TERSE; + jresult = (int)result; + return jresult; +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_output_get_flags___(void * jarg1) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (unsigned int)nft_ctx_output_get_flags(arg1); + jresult = (unsigned int)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_output_set_flags___(void * jarg1, unsigned int jarg2) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int arg2 ; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (unsigned int)jarg2; + nft_ctx_output_set_flags(arg1,arg2); +} + + +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_output_get_debug___(void * jarg1) { + unsigned int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (unsigned int)nft_ctx_output_get_debug(arg1); + jresult = (unsigned int)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_output_set_debug___(void * jarg1, unsigned int jarg2) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + unsigned int arg2 ; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (unsigned int)jarg2; + nft_ctx_output_set_debug(arg1,arg2); +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_buffer_output___(void * jarg1) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (int)nft_ctx_buffer_output(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_unbuffer_output___(void * jarg1) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (int)nft_ctx_unbuffer_output(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_get_output_buffer___(void * jarg1) { + char * jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *result = 0 ; + + arg1 = (struct nft_ctx *)jarg1; + result = (char *)nft_ctx_get_output_buffer(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_buffer_error___(void * jarg1) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (int)nft_ctx_buffer_error(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_unbuffer_error___(void * jarg1) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + result = (int)nft_ctx_unbuffer_error(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_get_error_buffer___(void * jarg1) { + char * jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *result = 0 ; + + arg1 = (struct nft_ctx *)jarg1; + result = (char *)nft_ctx_get_error_buffer(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_add_include_path___(void * jarg1, char * jarg2) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (char *)jarg2; + result = (int)nft_ctx_add_include_path(arg1,(char const *)arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_clear_include_paths___(void * jarg1) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + + arg1 = (struct nft_ctx *)jarg1; + nft_ctx_clear_include_paths(arg1); +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_add_var___(void * jarg1, char * jarg2) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (char *)jarg2; + result = (int)nft_ctx_add_var(arg1,(char const *)arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_ctx_clear_vars___(void * jarg1) { + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + + arg1 = (struct nft_ctx *)jarg1; + nft_ctx_clear_vars(arg1); +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_run_cmd_from_buffer___(void * jarg1, char * jarg2) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (char *)jarg2; + result = (int)nft_run_cmd_from_buffer(arg1,(char const *)arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_LibNftablesfBindingsfNative_nft_run_cmd_from_filename___(void * jarg1, char * jarg2) { + int jresult ; + struct nft_ctx *arg1 = (struct nft_ctx *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (struct nft_ctx *)jarg1; + arg2 = (char *)jarg2; + result = (int)nft_run_cmd_from_filename(arg1,(char const *)arg2); + jresult = result; + return jresult; +} + + +#ifdef __cplusplus +} +#endif + diff --git a/src/LibNftables.Bindings/Generated/nft_debug_level.cs b/src/LibNftables.Bindings/Generated/nft_debug_level.cs new file mode 100644 index 0000000..5277e05 --- /dev/null +++ b/src/LibNftables.Bindings/Generated/nft_debug_level.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (https://www.swig.org). +// Version 4.3.0 +// +// Do not make changes to this file unless you know what you are doing - modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace LibNftables.Bindings.Native { + +public enum nft_debug_level { + NFT_DEBUG_SCANNER = 1, + NFT_DEBUG_PARSER = 2, + NFT_DEBUG_EVALUATION = 4, + NFT_DEBUG_NETLINK = 8, + NFT_DEBUG_MNL = 16, + NFT_DEBUG_PROTO_CTX = 32, + NFT_DEBUG_SEGTREE = 64 +} + +} diff --git a/src/LibNftables.Bindings/Generated/nft_optimize_flags.cs b/src/LibNftables.Bindings/Generated/nft_optimize_flags.cs new file mode 100644 index 0000000..648da08 --- /dev/null +++ b/src/LibNftables.Bindings/Generated/nft_optimize_flags.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------------------------ +// +// +// This file was automatically generated by SWIG (https://www.swig.org). +// Version 4.3.0 +// +// Do not make changes to this file unless you know what you are doing - modify +// the SWIG interface file instead. +//------------------------------------------------------------------------------ + +namespace LibNftables.Bindings.Native { + +public enum nft_optimize_flags { + NFT_OPTIMIZE_ENABLED = 1 +} + +} diff --git a/src/LibNftables.Bindings/LibNftables.Bindings.csproj b/src/LibNftables.Bindings/LibNftables.Bindings.csproj new file mode 100644 index 0000000..9e3f320 --- /dev/null +++ b/src/LibNftables.Bindings/LibNftables.Bindings.csproj @@ -0,0 +1,31 @@ + + + + net10.0 + enable + enable + $(NoWarn);CS8981;CA2255 + + + + + + + + + + + + + + + diff --git a/src/LibNftables.Bindings/NativeLibraryBootstrap.cs b/src/LibNftables.Bindings/NativeLibraryBootstrap.cs new file mode 100644 index 0000000..6310526 --- /dev/null +++ b/src/LibNftables.Bindings/NativeLibraryBootstrap.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace LibNftables.Bindings; + +internal static class NativeLibraryBootstrap +{ + private const string DllImportName = "LibNftablesBindings"; + + [ModuleInitializer] + internal static void Initialize() + { + NativeLibrary.SetDllImportResolver(typeof(NativeLibraryBootstrap).Assembly, Resolve); + } + + private static IntPtr Resolve(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + { + if (!string.Equals(libraryName, DllImportName, StringComparison.Ordinal)) + { + return IntPtr.Zero; + } + + string? baseDir = Path.GetDirectoryName(assembly.Location); + if (string.IsNullOrEmpty(baseDir)) + { + return IntPtr.Zero; + } + + string[] candidates = + { + Path.Combine(baseDir, "libLibNftablesBindings.so"), + Path.Combine(baseDir, "runtimes", "linux-x64", "native", "libLibNftablesBindings.so"), + }; + + foreach (string candidate in candidates) + { + if (!File.Exists(candidate)) + { + continue; + } + + if (NativeLibrary.TryLoad(candidate, out IntPtr handle)) + { + return handle; + } + } + + return IntPtr.Zero; + } +} diff --git a/src/LibNftables.Bindings/runtimes/linux-x64/native/libLibNftablesBindings.so b/src/LibNftables.Bindings/runtimes/linux-x64/native/libLibNftablesBindings.so new file mode 100755 index 0000000000000000000000000000000000000000..bd1a4af7ed7c55b85cff6d19fc5f1ad4c3ef4b03 GIT binary patch literal 24664 zcmeHP3v^u7b-l7=EI?ROV!+r99>AtH7)1sH=HoE7J|2NADf$?bgg%Wlqfd}VTBDJX z$p?XLFdt`$@N+3E6*LJhl%h6#OrblUS}rffCLcPT;Tb7g8{CT;rZABtc9Phm(`DkW&z>GsN5-@+@{PSCVF4km|I zx^{=wdU0ZgD^D_t9f@RD{AstoxXz2?oGig&w^~t*^jX3FY+T5Cf}~5O;m7f?-nROs zSdMdhf@1d>*ioFh79T4%a(mhGQq1uSa`U=xbKs*8pEY$Y>QBBpXGZH4|9!@TXTSWw z>^D{0J0G9;Fg39VpHJdLaZ+xE1EZUk>^tG+txx(lt(&F%FYn$^JXtWdY1n^Ual;%n zLb?m^k>bY&`8Y=i;9`8v#b+sV%NUmfFXHWsfh&0XQpU@Gm*Yc2;7aBMR$-$8pGqdG z7}o%6mwe=R9{#s`e)7Vuy-)2p9G?B=ybsqe`1ZcluWt5TIO~KkD_UFWvO`l|#QMId^Ad?)p3b_@c7+w|{f#wG*E@z3=otI^%(@n{Tb# zboX~oDfrjt-uT(NMW;O!-+R;i3|La-W zeJ{&?sm{{hpJvG$+-L0Xx51yRO4R6C*g%0>U9QvPr$kLIbmdc-cXU3XZ}CsFzCLL{ zmoEqEdL2)R^3%!0;IGp8EKv<-d->zp&jkAyKeKdyOH`}H&(V1+QR5uH=$GmImnfg* z|BFR#e@B>?b9a;8FNnvA^PiwV`SEkRqW=~4@3;K_HTSpN@e$`I)fta}vktv*P?3>rb-&AGqPD7mM6DN3Hlz zDs=gP#g8)I%Dlw$OKvw{wRTfB0d&fdPLGY}8O;*O)7n&!1mI1-C=b`QiOvF5cEJ$=zg zbEvH+;?`xZaoUGMPDgh%)YE-qL^WMgv!;yDi!g zCzk`6RaeD22YVyY_^&r@?qtZT|+ z$9v7MYO1fx!&rt%ceH;nuI)N{LY)I1cgRGbO6AYF$-h zQ`ONWi+wazHLk0vsLCT@RuE0itD387tD25xhj9$SRdtoM#}GoEd)(?kRYkD==)1qB zrKa-et?OFWRyEdCI1P>U&BqW#+D*-Gz)RD$YggCT9($*nYt|maPL)2bsy&8Kn(6q+ zqbG9M_6^3fo(=4}Tn=2zZ|a~o&ob;cRd*DA^+hJqHrScLZ>sJn{8CKeEPhjU`S@)c z?C6NZ9PYAlvG!Et<8d(RF*OrlRpsMVUohRV!0wG$r&Q+SncYQVvA&oYtjXu&FV)E@ z9=$dB_@oZH?lO1Ytjou5C>(aWqwPI|;fT{8ig%g)x9jrp+ujoi#XO!pm+=hM`FN+u zHo(6z0+`CjiyH*|WC)GeTz%2k%l6)|(-G_Ib-cSLL)B4v?da}_L_@u)Z;BqjQmKp^ zhq8gbvSq5aW;L#`t5)MXfpdXJTJDi9^hoslat8hiRe?s@roSRB&t!?}its69c?OUEYs)N-MEo8|YlJVWh+Ohulz%X6K6 zz7JLMJl$1O<;;&axP<77yr3$ctmZ>sf@Z6-Xd&}U>=Yf+3|A#3r*x+_?n~NNz zOR>S@)-_dp249$B@!Z7Vk+@Xx8@$}JQ{`fVr?#b(8@%L#>Q)#$9x0?sz~J!+D^-F9 zk4GP=(qQl>rC6ob8~kj8Z#DQ*gYPnUpTYMVygb99>LG*wgrPrd@brE`%2tCvMM&U? z!OOEjs@`t!ry2UA20z!}cNqNX20v!-^9+8c!SgFFqjq|8Is?-gn9jie{R{**y;~f- zbLN|$QYyG*JU$~i5!|%9cvmX$J6elM;N*7e7 z?LRC%SCJmd!)ku;d)A-(Z8#o%) zrO$Y*X*_Q^7%08(l|bn;2NTPnHIlg8Yo9pJ>whPW^j+zgchX2V5AB@bINeXBL?aW~CLPmC$9e3lW#j;Q{)pZ{V!Vb ze6OtcUne-)f5F>dO)i?Z6yrZNW)eUAg}41b^~&1*8gME5x6kv~f6l9)c>dSO*L&kj zJZ|Yz|B!NhUiF+wK~9(H3`}QWIs?-gn9jg-2BtGGoq_2L{GKyVFu(9}`Yk!##rgN+ z1_;|@?Dw7y#}EHUNuoyVDAs3+x9j1r7rPz!6|Ga1=;SEXIMuzzN{J zz)9c^p!z7890&S+Ov&%JQrS*TWIUy0BDpCyxYiztO|4?mC34(v;~ z(}lQxe7<3Eo578O6MNFzj?Y8jkRDx#`%8SbgOm3d#Es)~ufb6~Kfq@MoPN$Lw*7K&ne1yb*tc5tG;ZQ-Z}yw!2`n|@B)x~gEw;EZa0?9%YSU#p1JfCp&cJjA zrZX^|f$0qVzsi98{z`stg|DZ&&~Lt|FyLlJi|Qm7)cQs4hWtiGe%B?xfsuQO)Nf_# zTz&bCmDGQ9B-uwbt@utzMZS}b@Q;?{`~C#JcTthwG9Bc=|or$cq`-mjNf8>hVd1~e`fqI#)FKmlj(l}$RhPV zy|VKZ8fG(a6pV8_QaPLX{T5Fm>C5pX`j=p%K%J`gaGca0l?r?c6z-Jy_|PQ&eE}cx zBgd!k8?aG;J7+oGgr^DLnc}B$OYKf@yE2}s{Y?71wSK8uaS=AGl1cyj&?&$SL3>>N zQ1hpx`YWz}!o2J+;SXSA1|3~~VO%_{0ogA1@+YAKGjKMN^N`ej0(=3EaykBmUjjbU zJjPz;?fIO4rFpSVBi-kdpYgL@PR>uq;rv3pJ#TZZ=F|4FMbE=Xf8;Eefm>Z3W!}gB z<$U-K^Y;AGPvS&EegalJpVd4&HQ>vvZ_gur0leSPlg;mC@$&)uvFBGWD{|u*<9BZn_zcg6+?9jYKm&Th}-=6>ccg)-K(v!@OS#hq!7Zhq&Kfr~1$0zVML$Ngi+VTj%REFIs85DGUEd7XCH%KWh0u0bQbYC#>UW4fBfgP|8i; ztod{tvi0X#_}AEv&pM8L_`*r;`YpbN`Bp2Qdo?eurSW;zpRo4V&zTQcepcX;L+v(L z{0+?8>jgZ`{HW#sBh9DdkgZdZD8C3Mw#VWFaZC*>Ygg&%?oPbdX{QPA1DF>d?sGbO z`r1N0PB`9&IW(ccA=Td3+usw3N5W<0nKft;rnTyVK4S>EW%qaTVr0R@GHvqL5R0ZQZK1 zH5H&SYhOqwJkaNKg`#1azfTRK8tVr+RY5imRyHafv~t$e)~{Yw>(p0QH&rz|dRk3R zli{sNuD^w;!ZN23)9nN1oS$X6Og6H@JGMEvGF8+wi&nz3C$U+vW?UBGSFd%D$5I4( zil8y!J`YoKA|TB<%fVEV>Q19KXGKdgXtJhE*!Lvj!d(1|7h|SsYF4P@U2Q^C?dg1; zMspe|**xW$6KgpM@#>u%X+@WDY{psbFlL6`n*?AkVaGK zNYBhQlW=S+dq^Yhatf(=&gO(lZk7%ky61k8(gL0d;1Ym&Xjv_Yij@dUD~BB- zj?5#@?5VY;gr|Y!xgLxeXJk?p*76R z5lFk&YBUeWo=lP3JZv)zq#Qk12{tcrIkazC%kIg0y$jig-nra41R#dA^E0dwWStm2 zJ16IJ0{nx=5E*PHMr{&c^XI`y?SW!mllu8h57*Z9Dgzm+@qJ*5jf>Q$Z;r0 zE>maf)WQdO>#BFf4QCate$(9JCexKClgO|1$5 zu%91X7qSODrt_2)knl(;)xNyP6CCFUWJS;+S7I;k*8e{n(kVf}q4JK13G0&9ayGaDw+q;@E+-EB>}w_VT_+5RY*^#qR$-Y%lvS^&YC+ zHKX55o5i+&7?q?V_Cw2DZNc4E{L*jn`8YQ42vHvc#L0U*-S4!K9Oz$yCCl!B#TeBzNqV&_1rrJ-Ug5u}l zB5F$P7o-?>gVU*Ph#^_Vj;rDR-xqLklsiB_UpNIH>5rU0X?#oUu7&%5YmJMG +%} + +%include "stdint.i" + +/* FILE* based APIs are intentionally excluded from the managed facade. */ +%ignore nft_ctx_set_output; +%ignore nft_ctx_set_error; + +%include diff --git a/src/LibNftables/INftablesClient.cs b/src/LibNftables/INftablesClient.cs new file mode 100644 index 0000000..22504d0 --- /dev/null +++ b/src/LibNftables/INftablesClient.cs @@ -0,0 +1,103 @@ +namespace LibNftables; + +/// +/// Provides high-level nftables operations backed by libnftables. +/// +public interface INftablesClient +{ + /// + /// Validates a ruleset request using dry-run mode. + /// + /// The ruleset request to validate. + /// A cancellation token. + /// + /// A validation result. Invalid ruleset syntax or schema errors return = . + /// + /// Thrown when request input shape is invalid (for example, both text and file source provided). + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + NftValidationResult Validate(NftApplyRequest request, System.Threading.CancellationToken ct = default); + + /// + /// Asynchronously validates a ruleset request using dry-run mode. + /// + /// The ruleset request to validate. + /// A cancellation token. + /// A task that resolves to a validation result. + /// Thrown when request input shape is invalid (for example, both text and file source provided). + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + System.Threading.Tasks.Task ValidateAsync(NftApplyRequest request, System.Threading.CancellationToken ct = default); + + /// + /// Applies a ruleset request. + /// + /// The ruleset request to apply. + /// A cancellation token. + /// Thrown when request input shape is invalid or the ruleset cannot be parsed/validated. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + void Apply(NftApplyRequest request, System.Threading.CancellationToken ct = default); + + /// + /// Asynchronously applies a ruleset request. + /// + /// The ruleset request to apply. + /// A cancellation token. + /// A completed task when apply succeeds. + /// Thrown when request input shape is invalid or the ruleset cannot be parsed/validated. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + System.Threading.Tasks.Task ApplyAsync(NftApplyRequest request, System.Threading.CancellationToken ct = default); + + /// + /// Captures the current nftables ruleset from the system. + /// + /// A cancellation token. + /// A snapshot containing the exported ruleset text and capture time. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + NftSnapshot Snapshot(System.Threading.CancellationToken ct = default); + + /// + /// Asynchronously captures the current nftables ruleset from the system. + /// + /// A cancellation token. + /// A task that resolves to a snapshot. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + System.Threading.Tasks.Task SnapshotAsync(System.Threading.CancellationToken ct = default); + + /// + /// Restores ruleset state from a previously captured snapshot. + /// + /// The snapshot to restore. + /// A cancellation token. + /// Thrown when snapshot content is invalid. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + void Restore(NftSnapshot snapshot, System.Threading.CancellationToken ct = default); + + /// + /// Asynchronously restores ruleset state from a previously captured snapshot. + /// + /// The snapshot to restore. + /// A cancellation token. + /// A completed task when restore succeeds. + /// Thrown when snapshot content is invalid. + /// Thrown when insufficient privileges are available for runtime operation. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + /// Thrown for other native execution failures. + System.Threading.Tasks.Task RestoreAsync(NftSnapshot snapshot, System.Threading.CancellationToken ct = default); +} diff --git a/src/LibNftables/LibNftables.csproj b/src/LibNftables/LibNftables.csproj new file mode 100644 index 0000000..f110e65 --- /dev/null +++ b/src/LibNftables/LibNftables.csproj @@ -0,0 +1,15 @@ + + + + + + + + net10.0 + enable + enable + true + $(WarningsAsErrors);CS1591 + + + diff --git a/src/LibNftables/NftApplyRequest.cs b/src/LibNftables/NftApplyRequest.cs new file mode 100644 index 0000000..5323754 --- /dev/null +++ b/src/LibNftables/NftApplyRequest.cs @@ -0,0 +1,62 @@ +namespace LibNftables; + +/// +/// Represents an apply/validate request source and execution settings. +/// +public sealed class NftApplyRequest +{ + /// + /// Gets or sets ruleset command text source. + /// + /// Exactly one of or must be provided. + public string? RulesetText { get; set; } + + /// + /// Gets or sets ruleset file path source. + /// + /// Exactly one of or must be provided. + public string? RulesetFilePath { get; set; } + + /// + /// Gets or sets a value indicating whether execution should run in dry-run mode. + /// + public bool DryRun { get; set; } + + /// + /// Gets or sets input parser flags. + /// + public NftInputFlags InputFlags { get; set; } + + /// + /// Gets or sets output behavior flags. + /// + public NftOutputFlags OutputFlags { get; set; } + + /// + /// Gets or sets debug flags. + /// + public NftDebugLevel DebugFlags { get; set; } + + /// + /// Gets or sets optimize flags. + /// + public NftOptimizeFlags OptimizeFlags { get; set; } + + /// + /// Creates a request from command text. + /// + /// Ruleset command text. + /// Whether the request should run in dry-run mode. + /// A configured request instance. + public static NftApplyRequest FromText(string rulesetText, bool dryRun = false) + => new() { RulesetText = rulesetText, DryRun = dryRun }; + + /// + /// Creates a request from a file path. + /// + /// Path to file containing ruleset commands. + /// Whether the request should run in dry-run mode. + /// A configured request instance. + public static NftApplyRequest FromFile(string rulesetFilePath, bool dryRun = false) + => new() { RulesetFilePath = rulesetFilePath, DryRun = dryRun }; +} diff --git a/src/LibNftables/NftContext.cs b/src/LibNftables/NftContext.cs new file mode 100644 index 0000000..69a4442 --- /dev/null +++ b/src/LibNftables/NftContext.cs @@ -0,0 +1,219 @@ +using System; +using LibNftables.Bindings.Native; + +namespace LibNftables; + +/// +/// Low-level managed wrapper around a native nft_ctx. +/// +/// +/// Use for high-level workflows. This type is intended for advanced scenarios +/// requiring direct control over context flags and command execution. +/// +public sealed class NftContext : IDisposable +{ + private SWIGTYPE_p_nft_ctx? _ctx; + + /// + /// Initializes a new context instance. + /// + /// Native context flags passed to nft_ctx_new. + /// Thrown when native context creation fails. + public NftContext(uint contextFlags = 0) + { + _ctx = libnftables.nft_ctx_new(contextFlags); + if (_ctx is null) + { + throw new InvalidOperationException("Failed to create nftables context."); + } + } + + /// + /// Finalizes the context if it was not explicitly disposed. + /// + ~NftContext() + { + Dispose(disposing: false); + } + + /// + /// Gets or sets a value indicating whether command execution runs in dry-run mode. + /// + public bool DryRun + { + get => libnftables.nft_ctx_get_dry_run(Handle); + set => libnftables.nft_ctx_set_dry_run(Handle, value); + } + + /// + /// Gets or sets optimization flags. + /// + public NftOptimizeFlags OptimizeFlags + { + get => (NftOptimizeFlags)libnftables.nft_ctx_get_optimize(Handle); + set => libnftables.nft_ctx_set_optimize(Handle, (uint)value); + } + + /// + /// Gets or sets parser input flags. + /// + public NftInputFlags InputFlags + { + get => (NftInputFlags)libnftables.nft_ctx_input_get_flags(Handle); + set => _ = libnftables.nft_ctx_input_set_flags(Handle, (uint)value); + } + + /// + /// Gets or sets output formatting and behavior flags. + /// + public NftOutputFlags OutputFlags + { + get => (NftOutputFlags)libnftables.nft_ctx_output_get_flags(Handle); + set => libnftables.nft_ctx_output_set_flags(Handle, (uint)value); + } + + /// + /// Gets or sets debug output flags. + /// + public NftDebugLevel DebugFlags + { + get => (NftDebugLevel)libnftables.nft_ctx_output_get_debug(Handle); + set => libnftables.nft_ctx_output_set_debug(Handle, (uint)value); + } + + /// + /// Enables in-memory buffering for standard command output. + /// + /// Thrown when native operation fails. + public void BufferOutput() => EnsureSuccess(libnftables.nft_ctx_buffer_output(Handle), nameof(BufferOutput)); + + /// + /// Disables in-memory buffering for standard command output. + /// + /// Thrown when native operation fails. + public void UnbufferOutput() => EnsureSuccess(libnftables.nft_ctx_unbuffer_output(Handle), nameof(UnbufferOutput)); + + /// + /// Gets buffered standard command output. + /// + /// Buffered output, or when unavailable. + public string? GetOutputBuffer() => libnftables.nft_ctx_get_output_buffer(Handle); + + /// + /// Enables in-memory buffering for error output. + /// + /// Thrown when native operation fails. + public void BufferError() => EnsureSuccess(libnftables.nft_ctx_buffer_error(Handle), nameof(BufferError)); + + /// + /// Disables in-memory buffering for error output. + /// + /// Thrown when native operation fails. + public void UnbufferError() => EnsureSuccess(libnftables.nft_ctx_unbuffer_error(Handle), nameof(UnbufferError)); + + /// + /// Gets buffered error output. + /// + /// Buffered error output, or when unavailable. + public string? GetErrorBuffer() => libnftables.nft_ctx_get_error_buffer(Handle); + + /// + /// Adds an include search path. + /// + /// Filesystem include path. + /// Thrown when is null, empty, or whitespace. + /// Thrown when native operation fails. + public void AddIncludePath(string path) + { + ArgumentException.ThrowIfNullOrWhiteSpace(path); + EnsureSuccess(libnftables.nft_ctx_add_include_path(Handle, path), nameof(AddIncludePath)); + } + + /// + /// Clears all include search paths currently configured on this context. + /// + public void ClearIncludePaths() => libnftables.nft_ctx_clear_include_paths(Handle); + + /// + /// Adds a variable expression. + /// + /// Variable definition text understood by nftables parser. + /// Thrown when is null, empty, or whitespace. + /// Thrown when native operation fails. + public void AddVariable(string variableExpression) + { + ArgumentException.ThrowIfNullOrWhiteSpace(variableExpression); + EnsureSuccess(libnftables.nft_ctx_add_var(Handle, variableExpression), nameof(AddVariable)); + } + + /// + /// Clears all variables currently configured on this context. + /// + public void ClearVariables() => libnftables.nft_ctx_clear_vars(Handle); + + /// + /// Executes one or more nft commands from text. + /// + /// Command text. + /// Thrown when is null, empty, or whitespace. + /// Thrown when native operation fails. + public void RunCommand(string commandText) + { + ArgumentException.ThrowIfNullOrWhiteSpace(commandText); + EnsureSuccess(libnftables.nft_run_cmd_from_buffer(Handle, commandText), nameof(RunCommand)); + } + + /// + /// Executes nft commands loaded from a file. + /// + /// Path to the command file. + /// Thrown when is null, empty, or whitespace. + /// Thrown when native operation fails. + public void RunCommandFromFile(string path) + { + ArgumentException.ThrowIfNullOrWhiteSpace(path); + EnsureSuccess(libnftables.nft_run_cmd_from_filename(Handle, path), nameof(RunCommandFromFile)); + } + + /// + /// Releases native resources associated with this context. + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + private SWIGTYPE_p_nft_ctx Handle => _ctx ?? throw new ObjectDisposedException(nameof(NftContext)); + + private void Dispose(bool disposing) + { + if (_ctx is null) + { + return; + } + + libnftables.nft_ctx_free(_ctx); + _ctx = null; + } + + private void EnsureSuccess(int resultCode, string operation) + { + if (resultCode == 0) + { + return; + } + + string? error = null; + try + { + error = libnftables.nft_ctx_get_error_buffer(Handle); + } + catch + { + // Best effort only. + } + + throw NftErrorTranslator.FromOperationFailure(operation, resultCode, error); + } +} diff --git a/src/LibNftables/NftDerivedExceptions.cs b/src/LibNftables/NftDerivedExceptions.cs new file mode 100644 index 0000000..5d24d48 --- /dev/null +++ b/src/LibNftables/NftDerivedExceptions.cs @@ -0,0 +1,68 @@ +namespace LibNftables; + +/// +/// Indicates native runtime loading or initialization failed. +/// +public sealed class NftNativeLoadException : NftException +{ + /// + /// Initializes a new instance of the class. + /// + /// Error message. + /// Optional inner exception. + public NftNativeLoadException(string message, Exception? innerException = null) + : base(message, nativeErrorCode: 0, nativeErrorOutput: null, innerException) + { + } +} + +/// +/// Indicates insufficient privileges for requested operation. +/// +public sealed class NftPermissionException : NftException +{ + /// + /// Initializes a new instance of the class. + /// + /// Error message. + /// Native error code. + /// Native error output. + public NftPermissionException(string message, int nativeErrorCode, string? nativeErrorOutput) + : base(message, nativeErrorCode, nativeErrorOutput) + { + } +} + +/// +/// Indicates invalid request input or invalid nft command/ruleset syntax. +/// +public sealed class NftValidationException : NftException +{ + /// + /// Initializes a new instance of the class. + /// + /// Error message. + /// Native error code. + /// Native error output. + public NftValidationException(string message, int nativeErrorCode, string? nativeErrorOutput) + : base(message, nativeErrorCode, nativeErrorOutput) + { + } +} + +/// +/// Indicates an unsupported feature, platform, or runtime condition. +/// +public sealed class NftUnsupportedException : NftException +{ + /// + /// Initializes a new instance of the class. + /// + /// Error message. + /// Native error code. + /// Native error output. + public NftUnsupportedException(string message, int nativeErrorCode = 0, string? nativeErrorOutput = null) + : base(message, nativeErrorCode, nativeErrorOutput) + { + } +} diff --git a/src/LibNftables/NftEnums.cs b/src/LibNftables/NftEnums.cs new file mode 100644 index 0000000..ad8f8c5 --- /dev/null +++ b/src/LibNftables/NftEnums.cs @@ -0,0 +1,112 @@ +using System; + +namespace LibNftables; + +/// +/// Optimization flags for native nftables context. +/// +[Flags] +public enum NftOptimizeFlags : uint +{ + /// No optimization flags. + None = 0, + + /// Enables optimization. + Enabled = 0x1, +} + +/// +/// Input parser flags. +/// +[Flags] +public enum NftInputFlags : uint +{ + /// No input flags. + None = 0, + + /// Disable DNS lookups while parsing input. + NoDns = 1u << 0, + + /// Interpret input as JSON. + Json = 1u << 1, +} + +/// +/// Output formatting and behavior flags. +/// +[Flags] +public enum NftOutputFlags : uint +{ + /// No output flags. + None = 0, + + /// Enable reverse DNS names. + ReverseDns = 1u << 0, + + /// Enable service name rendering. + Service = 1u << 1, + + /// Enable stateless rendering mode. + Stateless = 1u << 2, + + /// Show object handles. + Handle = 1u << 3, + + /// Emit JSON output. + Json = 1u << 4, + + /// Echo commands in output. + Echo = 1u << 5, + + /// Show GUID values. + Guid = 1u << 6, + + /// Use numeric protocol identifiers. + NumericProto = 1u << 7, + + /// Use numeric priority values. + NumericPrio = 1u << 8, + + /// Use numeric symbol values. + NumericSymbol = 1u << 9, + + /// Use numeric time values. + NumericTime = 1u << 10, + + /// Enable all numeric output flags. + NumericAll = NumericProto | NumericPrio | NumericSymbol | NumericTime, + + /// Enable terse output format. + Terse = 1u << 11, +} + +/// +/// Debug output flags. +/// +[Flags] +public enum NftDebugLevel : uint +{ + /// No debug flags. + None = 0, + + /// Scanner debugging. + Scanner = 0x1, + + /// Parser debugging. + Parser = 0x2, + + /// Evaluation debugging. + Evaluation = 0x4, + + /// Netlink debugging. + Netlink = 0x8, + + /// libmnl debugging. + Mnl = 0x10, + + /// Protocol context debugging. + ProtoContext = 0x20, + + /// Segment tree debugging. + Segtree = 0x40, +} diff --git a/src/LibNftables/NftErrorTranslator.cs b/src/LibNftables/NftErrorTranslator.cs new file mode 100644 index 0000000..69b57b2 --- /dev/null +++ b/src/LibNftables/NftErrorTranslator.cs @@ -0,0 +1,47 @@ +namespace LibNftables; + +internal static class NftErrorTranslator +{ + internal static NftException FromOperationFailure(string operation, int resultCode, string? nativeError) + { + string trimmed = nativeError?.Trim() ?? string.Empty; + string message = string.IsNullOrWhiteSpace(trimmed) + ? $"{operation} failed with native error code {resultCode}." + : $"{operation} failed with native error code {resultCode}: {trimmed}"; + + if (ContainsAny(trimmed, "Operation not permitted", "Permission denied", "CAP_NET_ADMIN")) + { + return new NftPermissionException(message, resultCode, nativeError); + } + + if (ContainsAny(trimmed, "syntax error", "parse error", "Could not process rule", "No such file or directory")) + { + return new NftValidationException(message, resultCode, nativeError); + } + + if (ContainsAny(trimmed, "not supported", "unsupported")) + { + return new NftUnsupportedException(message, resultCode, nativeError); + } + + return new NftException(message, resultCode, nativeError); + } + + private static bool ContainsAny(string value, params string[] candidates) + { + if (string.IsNullOrWhiteSpace(value)) + { + return false; + } + + foreach (string candidate in candidates) + { + if (value.Contains(candidate, System.StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } +} diff --git a/src/LibNftables/NftException.cs b/src/LibNftables/NftException.cs new file mode 100644 index 0000000..7f10542 --- /dev/null +++ b/src/LibNftables/NftException.cs @@ -0,0 +1,33 @@ +using System; + +namespace LibNftables; + +/// +/// Base exception for managed nftables failures. +/// +public class NftException : InvalidOperationException +{ + /// + /// Initializes a new exception instance. + /// + /// Error message. + /// Native error code, when available. + /// Native error output, when available. + /// Optional inner exception. + public NftException(string message, int nativeErrorCode = 0, string? nativeErrorOutput = null, Exception? innerException = null) + : base(message, innerException) + { + NativeErrorCode = nativeErrorCode; + NativeErrorOutput = nativeErrorOutput; + } + + /// + /// Gets the native error code. + /// + public int NativeErrorCode { get; } + + /// + /// Gets native error output text. + /// + public string? NativeErrorOutput { get; } +} diff --git a/src/LibNftables/NftRuntimeGuard.cs b/src/LibNftables/NftRuntimeGuard.cs new file mode 100644 index 0000000..42d4a8e --- /dev/null +++ b/src/LibNftables/NftRuntimeGuard.cs @@ -0,0 +1,63 @@ +using System.Runtime.InteropServices; + +namespace LibNftables; + +internal static class NftRuntimeGuard +{ + private static readonly object Sync = new(); + private static bool initialized; + private static Exception? failure; + + internal static void EnsureInitializedForLinuxX64() + { + lock (Sync) + { + if (initialized) + { + if (failure is not null) + { + throw failure; + } + + return; + } + + try + { + if (!OperatingSystem.IsLinux()) + { + throw new NftUnsupportedException("libnftables managed API supports Linux only."); + } + + if (RuntimeInformation.ProcessArchitecture != Architecture.X64) + { + throw new NftUnsupportedException( + $"libnftables managed API currently supports Linux x64 only. Current architecture: {RuntimeInformation.ProcessArchitecture}."); + } + + using var probe = new NftContext(); + } + catch (NftException ex) + { + failure = ex; + initialized = true; + throw; + } + catch (Exception ex) when ( + ex is DllNotFoundException or + BadImageFormatException or + EntryPointNotFoundException or + TypeInitializationException) + { + var wrapped = new NftNativeLoadException( + "Failed to load native libnftables runtime. Ensure system package/lib is installed and loadable.", + ex); + failure = wrapped; + initialized = true; + throw wrapped; + } + + initialized = true; + } + } +} diff --git a/src/LibNftables/NftSnapshot.cs b/src/LibNftables/NftSnapshot.cs new file mode 100644 index 0000000..cfb3a11 --- /dev/null +++ b/src/LibNftables/NftSnapshot.cs @@ -0,0 +1,8 @@ +namespace LibNftables; + +/// +/// Represents an exported nftables ruleset snapshot. +/// +/// Captured ruleset text. +/// Capture timestamp in UTC. +public sealed record NftSnapshot(string RulesetText, System.DateTimeOffset CapturedAtUtc); diff --git a/src/LibNftables/NftValidationResult.cs b/src/LibNftables/NftValidationResult.cs new file mode 100644 index 0000000..e2536a8 --- /dev/null +++ b/src/LibNftables/NftValidationResult.cs @@ -0,0 +1,9 @@ +namespace LibNftables; + +/// +/// Represents the outcome of ruleset validation. +/// +/// Indicates whether validation succeeded. +/// Captured standard output, when available. +/// Validation diagnostics or error output, when available. +public sealed record NftValidationResult(bool IsValid, string? Output, string? Diagnostics); diff --git a/src/LibNftables/NftablesClient.cs b/src/LibNftables/NftablesClient.cs new file mode 100644 index 0000000..7742285 --- /dev/null +++ b/src/LibNftables/NftablesClient.cs @@ -0,0 +1,179 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace LibNftables; + +/// +/// Default high-level nftables client implementation. +/// +/// +/// This client wraps and applies a command-centric workflow: +/// validate (dry-run), apply, snapshot, and restore. +/// +public sealed class NftablesClient : INftablesClient +{ + private readonly NftablesClientOptions _options; + private readonly System.Func _contextFactory; + + /// + /// Initializes a new instance of the class. + /// + /// Optional client options. + /// Thrown when runtime/platform is unsupported. + /// Thrown when required native runtime components cannot be loaded. + public NftablesClient(NftablesClientOptions? options = null) + : this(options, static () => new NftContext()) + { + } + + internal NftablesClient(NftablesClientOptions? options, System.Func contextFactory) + { + _options = options ?? new NftablesClientOptions(); + _contextFactory = contextFactory; + NftRuntimeGuard.EnsureInitializedForLinuxX64(); + } + + /// + public NftValidationResult Validate(NftApplyRequest request, CancellationToken ct = default) + { + ct.ThrowIfCancellationRequested(); + ValidateRequest(request); + + try + { + CommandExecutionResult result = Execute(request, forceDryRun: true, ct); + return new NftValidationResult(true, result.Output, result.Error); + } + catch (NftValidationException ex) + { + return new NftValidationResult(false, null, ex.NativeErrorOutput ?? ex.Message); + } + } + + /// + public Task ValidateAsync(NftApplyRequest request, CancellationToken ct = default) + => Task.FromResult(Validate(request, ct)); + + /// + public void Apply(NftApplyRequest request, CancellationToken ct = default) + { + ct.ThrowIfCancellationRequested(); + ValidateRequest(request); + _ = Execute(request, forceDryRun: null, ct); + } + + /// + public Task ApplyAsync(NftApplyRequest request, CancellationToken ct = default) + { + Apply(request, ct); + return Task.CompletedTask; + } + + /// + public NftSnapshot Snapshot(CancellationToken ct = default) + { + ct.ThrowIfCancellationRequested(); + + NftApplyRequest request = NftApplyRequest.FromText(_options.SnapshotCommandText, dryRun: false); + CommandExecutionResult result = Execute(request, forceDryRun: null, ct); + string snapshotText = result.Output ?? string.Empty; + + if (string.IsNullOrWhiteSpace(snapshotText)) + { + throw new NftException("Snapshot returned an empty ruleset output.", nativeErrorOutput: result.Error); + } + + return new NftSnapshot(snapshotText, System.DateTimeOffset.UtcNow); + } + + /// + public Task SnapshotAsync(CancellationToken ct = default) + => Task.FromResult(Snapshot(ct)); + + /// + public void Restore(NftSnapshot snapshot, CancellationToken ct = default) + { + ct.ThrowIfCancellationRequested(); + + if (snapshot is null) + { + throw new NftValidationException("Snapshot must not be null.", 0, null); + } + + if (string.IsNullOrWhiteSpace(snapshot.RulesetText)) + { + throw new NftValidationException("Snapshot ruleset text must not be empty.", 0, null); + } + + NftApplyRequest request = NftApplyRequest.FromText(snapshot.RulesetText, dryRun: false); + _ = Execute(request, forceDryRun: null, ct); + } + + /// + public Task RestoreAsync(NftSnapshot snapshot, CancellationToken ct = default) + { + Restore(snapshot, ct); + return Task.CompletedTask; + } + + private CommandExecutionResult Execute(NftApplyRequest request, bool? forceDryRun, CancellationToken ct) + { + ct.ThrowIfCancellationRequested(); + + using NftContext ctx = _contextFactory(); + ConfigureContext(ctx, request, forceDryRun); + + if (!string.IsNullOrWhiteSpace(request.RulesetText)) + { + ctx.RunCommand(request.RulesetText); + } + else + { + ctx.RunCommandFromFile(request.RulesetFilePath!); + } + + return new CommandExecutionResult(ctx.GetOutputBuffer(), ctx.GetErrorBuffer()); + } + + private void ConfigureContext(NftContext ctx, NftApplyRequest request, bool? forceDryRun) + { + ctx.DryRun = forceDryRun ?? request.DryRun; + ctx.InputFlags = _options.DefaultInputFlags | request.InputFlags; + ctx.OutputFlags = _options.DefaultOutputFlags | request.OutputFlags; + ctx.DebugFlags = _options.DefaultDebugFlags | request.DebugFlags; + ctx.OptimizeFlags = _options.DefaultOptimizeFlags | request.OptimizeFlags; + + if (_options.BufferOutput) + { + ctx.BufferOutput(); + } + + if (_options.BufferError) + { + ctx.BufferError(); + } + } + + private static void ValidateRequest(NftApplyRequest request) + { + if (request is null) + { + throw new NftValidationException("Request must not be null.", 0, null); + } + + bool hasText = !string.IsNullOrWhiteSpace(request.RulesetText); + bool hasFile = !string.IsNullOrWhiteSpace(request.RulesetFilePath); + + if (hasText == hasFile) + { + throw new NftValidationException("Exactly one source must be provided: RulesetText or RulesetFilePath.", 0, null); + } + + if (hasFile && !System.IO.File.Exists(request.RulesetFilePath)) + { + throw new NftValidationException($"Ruleset file was not found: '{request.RulesetFilePath}'.", 0, null); + } + } + + private sealed record CommandExecutionResult(string? Output, string? Error); +} diff --git a/src/LibNftables/NftablesClientOptions.cs b/src/LibNftables/NftablesClientOptions.cs new file mode 100644 index 0000000..6fe2fa9 --- /dev/null +++ b/src/LibNftables/NftablesClientOptions.cs @@ -0,0 +1,42 @@ +namespace LibNftables; + +/// +/// Configures default behavior for . +/// +public sealed class NftablesClientOptions +{ + /// + /// Gets or sets default input flags applied to each request. + /// + public NftInputFlags DefaultInputFlags { get; set; } + + /// + /// Gets or sets default output flags applied to each request. + /// + public NftOutputFlags DefaultOutputFlags { get; set; } + + /// + /// Gets or sets default debug flags applied to each request. + /// + public NftDebugLevel DefaultDebugFlags { get; set; } + + /// + /// Gets or sets default optimize flags applied to each request. + /// + public NftOptimizeFlags DefaultOptimizeFlags { get; set; } + + /// + /// Gets or sets a value indicating whether output buffering is enabled automatically. + /// + public bool BufferOutput { get; set; } = true; + + /// + /// Gets or sets a value indicating whether error buffering is enabled automatically. + /// + public bool BufferError { get; set; } = true; + + /// + /// Gets or sets command text used for snapshot capture. + /// + public string SnapshotCommandText { get; set; } = "list ruleset"; +} diff --git a/tests/LibNftables.Tests/LibNftables.Tests.csproj b/tests/LibNftables.Tests/LibNftables.Tests.csproj new file mode 100644 index 0000000..7ba37e7 --- /dev/null +++ b/tests/LibNftables.Tests/LibNftables.Tests.csproj @@ -0,0 +1,25 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/LibNftables.Tests/NftContextTests.cs b/tests/LibNftables.Tests/NftContextTests.cs new file mode 100644 index 0000000..79fce66 --- /dev/null +++ b/tests/LibNftables.Tests/NftContextTests.cs @@ -0,0 +1,142 @@ +using System.Globalization; + +namespace LibNftables.Tests; + +public sealed class NftContextTests +{ + [Fact] + public void ContextFlagsRoundTrip_Works() + { + if (!TryCreateContext(out var ctx)) + { + return; + } + + using (ctx) + { + ctx.DryRun = true; + Assert.True(ctx.DryRun); + + ctx.OptimizeFlags = NftOptimizeFlags.Enabled; + Assert.True(ctx.OptimizeFlags.HasFlag(NftOptimizeFlags.Enabled)); + + ctx.InputFlags = NftInputFlags.NoDns | NftInputFlags.Json; + Assert.True(ctx.InputFlags.HasFlag(NftInputFlags.NoDns)); + Assert.True(ctx.InputFlags.HasFlag(NftInputFlags.Json)); + + ctx.OutputFlags = NftOutputFlags.Json | NftOutputFlags.Echo | NftOutputFlags.Terse; + Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Json)); + Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Echo)); + Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Terse)); + + ctx.DebugFlags = NftDebugLevel.Parser | NftDebugLevel.Scanner; + Assert.True(ctx.DebugFlags.HasFlag(NftDebugLevel.Parser)); + Assert.True(ctx.DebugFlags.HasFlag(NftDebugLevel.Scanner)); + } + } + + [Fact] + public void InvalidCommand_ThrowsNftExceptionWithErrorBuffer() + { + if (!TryCreateContext(out var ctx)) + { + return; + } + + using (ctx) + { + ctx.DryRun = true; + ctx.BufferError(); + + var ex = Assert.ThrowsAny(() => ctx.RunCommand("this is not valid nft syntax")); + Assert.NotEqual(0, ex.NativeErrorCode); + Assert.False(string.IsNullOrWhiteSpace(ex.NativeErrorOutput)); + } + } + + [Fact] + public void ValidDryRunCommand_CanExecuteAndBufferOutput() + { + if (!TryCreateContext(out var ctx)) + { + return; + } + + if (!HasCapNetAdmin()) + { + return; + } + + using (ctx) + { + ctx.DryRun = true; + ctx.BufferOutput(); + ctx.BufferError(); + + ctx.RunCommand("add table inet swig_test"); + var output = ctx.GetOutputBuffer(); + var error = ctx.GetErrorBuffer(); + + Assert.NotNull(output); + Assert.True(string.IsNullOrEmpty(error), $"Unexpected error buffer: {error}"); + } + } + + private static bool HasCapNetAdmin() + { + const int capNetAdminBit = 12; + const ulong mask = 1UL << capNetAdminBit; + + try + { + foreach (var line in File.ReadLines("/proc/self/status")) + { + if (!line.StartsWith("CapEff:", StringComparison.Ordinal)) + { + continue; + } + + var hex = line["CapEff:".Length..].Trim(); + if (ulong.TryParse(hex, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var value)) + { + return (value & mask) != 0; + } + } + } + catch + { + // If capability probing fails, keep test conservative. + } + + return false; + } + + private static bool TryCreateContext(out NftContext context) + { + try + { + context = new NftContext(); + return true; + } + catch (DllNotFoundException) + { + context = null!; + return false; + } + catch (TypeInitializationException ex) when (ex.InnerException is DllNotFoundException) + { + context = null!; + return false; + } + catch (BadImageFormatException) + { + context = null!; + return false; + } + catch (EntryPointNotFoundException) + { + context = null!; + return false; + } + } +} diff --git a/tests/LibNftables.Tests/NftEnumTests.cs b/tests/LibNftables.Tests/NftEnumTests.cs new file mode 100644 index 0000000..6cd4024 --- /dev/null +++ b/tests/LibNftables.Tests/NftEnumTests.cs @@ -0,0 +1,25 @@ +namespace LibNftables.Tests; + +public sealed class NftEnumTests +{ + [Fact] + public void OutputNumericAll_ComposesIndividualNumericFlags() + { + var expected = NftOutputFlags.NumericProto | + NftOutputFlags.NumericPrio | + NftOutputFlags.NumericSymbol | + NftOutputFlags.NumericTime; + + Assert.Equal(NftOutputFlags.NumericAll, expected); + } + + [Fact] + public void DebugFlags_AreBitwiseDistinct() + { + var combined = NftDebugLevel.Scanner | NftDebugLevel.Parser | NftDebugLevel.Evaluation; + + Assert.True(combined.HasFlag(NftDebugLevel.Scanner)); + Assert.True(combined.HasFlag(NftDebugLevel.Parser)); + Assert.True(combined.HasFlag(NftDebugLevel.Evaluation)); + } +} diff --git a/tests/LibNftables.Tests/NftablesClientTests.cs b/tests/LibNftables.Tests/NftablesClientTests.cs new file mode 100644 index 0000000..2173a11 --- /dev/null +++ b/tests/LibNftables.Tests/NftablesClientTests.cs @@ -0,0 +1,66 @@ +namespace LibNftables.Tests; + +public sealed class NftablesClientTests +{ + [Fact] + public void Apply_WithBothTextAndFile_ThrowsValidationException() + { + var client = new NftablesClient(); + var request = new NftApplyRequest + { + RulesetText = "flush ruleset", + RulesetFilePath = "/tmp/does-not-matter.nft", + }; + + Assert.Throws(() => client.Apply(request)); + } + + [Fact] + public void Validate_InvalidRuleset_ReturnsInvalidResult() + { + var client = new NftablesClient(); + var request = NftApplyRequest.FromText("this is not valid nft syntax"); + + NftValidationResult result = client.Validate(request); + + Assert.False(result.IsValid); + Assert.False(string.IsNullOrWhiteSpace(result.Diagnostics)); + } + + [Fact] + public async System.Threading.Tasks.Task ValidateAsync_InvalidRuleset_ReturnsInvalidResult() + { + var client = new NftablesClient(); + var request = NftApplyRequest.FromText("this is not valid nft syntax"); + + NftValidationResult result = await client.ValidateAsync(request); + + Assert.False(result.IsValid); + Assert.False(string.IsNullOrWhiteSpace(result.Diagnostics)); + } + + [Fact] + public void Apply_InvalidRuleset_ThrowsValidationException() + { + var client = new NftablesClient(); + var request = NftApplyRequest.FromText("this is not valid nft syntax"); + + Assert.Throws(() => client.Apply(request)); + } + + [Fact] + public void Snapshot_WithInsufficientPrivileges_ThrowsPermissionOrReturnsRuleset() + { + var client = new NftablesClient(); + + try + { + NftSnapshot snapshot = client.Snapshot(); + Assert.False(string.IsNullOrWhiteSpace(snapshot.RulesetText)); + } + catch (NftPermissionException) + { + // Expected in unprivileged environments. + } + } +}