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 0000000..bd1a4af
Binary files /dev/null and b/src/LibNftables.Bindings/runtimes/linux-x64/native/libLibNftablesBindings.so differ
diff --git a/src/LibNftables.Bindings/swig/libnftables.i b/src/LibNftables.Bindings/swig/libnftables.i
new file mode 100644
index 0000000..2037708
--- /dev/null
+++ b/src/LibNftables.Bindings/swig/libnftables.i
@@ -0,0 +1,13 @@
+%module libnftables
+
+%{
+#include
+%}
+
+%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.
+ }
+ }
+}