Add src files

This commit is contained in:
Vibe Myass
2026-03-11 01:40:27 +00:00
parent b6617bb221
commit 05fda54da2
32 changed files with 2852 additions and 0 deletions

9
LibNftables.slnx Normal file
View File

@@ -0,0 +1,9 @@
<Solution>
<Folder Name="/src/">
<Project Path="src/LibNftables.Bindings/LibNftables.Bindings.csproj" />
<Project Path="src/LibNftables/LibNftables.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/LibNftables.Tests/LibNftables.Tests.csproj" />
</Folder>
</Solution>

59
README.md Normal file
View File

@@ -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"));
}
```

View File

@@ -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

28
eng/build-native.sh Executable file
View File

@@ -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"

22
eng/regen-bindings.sh Executable file
View File

@@ -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"

View File

@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
// <auto-generated />
//
// 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;
}
}
}

View File

@@ -0,0 +1,148 @@
//------------------------------------------------------------------------------
// <auto-generated />
//
// 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();
}
}

View File

@@ -0,0 +1,349 @@
//------------------------------------------------------------------------------
// <auto-generated />
//
// 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);
}
}

View File

@@ -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 <stdlib.h>
#include <string.h>
#include <stdio.h>
/* 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 <nftables/libnftables.h>
#include <stdint.h> // 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

View File

@@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <auto-generated />
//
// 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
}
}

View File

@@ -0,0 +1,17 @@
//------------------------------------------------------------------------------
// <auto-generated />
//
// 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
}
}

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CS8981;CA2255</NoWarn>
</PropertyGroup>
<ItemGroup>
<None Include="runtimes/linux-x64/native/libLibNftablesBindings.so"
CopyToOutputDirectory="PreserveNewest"
Pack="true"
PackagePath="runtimes/linux-x64/native/" />
</ItemGroup>
<Target Name="BuildNativeWrapper"
BeforeTargets="BeforeBuild"
Condition="$([MSBuild]::IsOSPlatform('Linux'))">
<Exec Command="bash ../../eng/build-native.sh"
WorkingDirectory="$(MSBuildProjectDirectory)" />
</Target>
<Target Name="CopyNativeWrapperToOutputRoot"
AfterTargets="Build"
Condition="$([MSBuild]::IsOSPlatform('Linux'))">
<Copy SourceFiles="$(MSBuildProjectDirectory)/runtimes/linux-x64/native/libLibNftablesBindings.so"
DestinationFolder="$(OutDir)" />
</Target>
</Project>

View File

@@ -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;
}
}

View File

@@ -0,0 +1,13 @@
%module libnftables
%{
#include <nftables/libnftables.h>
%}
%include "stdint.i"
/* FILE* based APIs are intentionally excluded from the managed facade. */
%ignore nft_ctx_set_output;
%ignore nft_ctx_set_error;
%include <nftables/libnftables.h>

View File

@@ -0,0 +1,103 @@
namespace LibNftables;
/// <summary>
/// Provides high-level nftables operations backed by <c>libnftables</c>.
/// </summary>
public interface INftablesClient
{
/// <summary>
/// Validates a ruleset request using dry-run mode.
/// </summary>
/// <param name="request">The ruleset request to validate.</param>
/// <param name="ct">A cancellation token.</param>
/// <returns>
/// A validation result. Invalid ruleset syntax or schema errors return <see cref="NftValidationResult.IsValid"/> = <see langword="false"/>.
/// </returns>
/// <exception cref="NftValidationException">Thrown when request input shape is invalid (for example, both text and file source provided).</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
NftValidationResult Validate(NftApplyRequest request, System.Threading.CancellationToken ct = default);
/// <summary>
/// Asynchronously validates a ruleset request using dry-run mode.
/// </summary>
/// <param name="request">The ruleset request to validate.</param>
/// <param name="ct">A cancellation token.</param>
/// <returns>A task that resolves to a validation result.</returns>
/// <exception cref="NftValidationException">Thrown when request input shape is invalid (for example, both text and file source provided).</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
System.Threading.Tasks.Task<NftValidationResult> ValidateAsync(NftApplyRequest request, System.Threading.CancellationToken ct = default);
/// <summary>
/// Applies a ruleset request.
/// </summary>
/// <param name="request">The ruleset request to apply.</param>
/// <param name="ct">A cancellation token.</param>
/// <exception cref="NftValidationException">Thrown when request input shape is invalid or the ruleset cannot be parsed/validated.</exception>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
void Apply(NftApplyRequest request, System.Threading.CancellationToken ct = default);
/// <summary>
/// Asynchronously applies a ruleset request.
/// </summary>
/// <param name="request">The ruleset request to apply.</param>
/// <param name="ct">A cancellation token.</param>
/// <returns>A completed task when apply succeeds.</returns>
/// <exception cref="NftValidationException">Thrown when request input shape is invalid or the ruleset cannot be parsed/validated.</exception>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
System.Threading.Tasks.Task ApplyAsync(NftApplyRequest request, System.Threading.CancellationToken ct = default);
/// <summary>
/// Captures the current nftables ruleset from the system.
/// </summary>
/// <param name="ct">A cancellation token.</param>
/// <returns>A snapshot containing the exported ruleset text and capture time.</returns>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
NftSnapshot Snapshot(System.Threading.CancellationToken ct = default);
/// <summary>
/// Asynchronously captures the current nftables ruleset from the system.
/// </summary>
/// <param name="ct">A cancellation token.</param>
/// <returns>A task that resolves to a snapshot.</returns>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
System.Threading.Tasks.Task<NftSnapshot> SnapshotAsync(System.Threading.CancellationToken ct = default);
/// <summary>
/// Restores ruleset state from a previously captured snapshot.
/// </summary>
/// <param name="snapshot">The snapshot to restore.</param>
/// <param name="ct">A cancellation token.</param>
/// <exception cref="NftValidationException">Thrown when snapshot content is invalid.</exception>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
void Restore(NftSnapshot snapshot, System.Threading.CancellationToken ct = default);
/// <summary>
/// Asynchronously restores ruleset state from a previously captured snapshot.
/// </summary>
/// <param name="snapshot">The snapshot to restore.</param>
/// <param name="ct">A cancellation token.</param>
/// <returns>A completed task when restore succeeds.</returns>
/// <exception cref="NftValidationException">Thrown when snapshot content is invalid.</exception>
/// <exception cref="NftPermissionException">Thrown when insufficient privileges are available for runtime operation.</exception>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
/// <exception cref="NftException">Thrown for other native execution failures.</exception>
System.Threading.Tasks.Task RestoreAsync(NftSnapshot snapshot, System.Threading.CancellationToken ct = default);
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\LibNftables.Bindings\LibNftables.Bindings.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<WarningsAsErrors>$(WarningsAsErrors);CS1591</WarningsAsErrors>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,62 @@
namespace LibNftables;
/// <summary>
/// Represents an apply/validate request source and execution settings.
/// </summary>
public sealed class NftApplyRequest
{
/// <summary>
/// Gets or sets ruleset command text source.
/// </summary>
/// <remarks>Exactly one of <see cref="RulesetText"/> or <see cref="RulesetFilePath"/> must be provided.</remarks>
public string? RulesetText { get; set; }
/// <summary>
/// Gets or sets ruleset file path source.
/// </summary>
/// <remarks>Exactly one of <see cref="RulesetText"/> or <see cref="RulesetFilePath"/> must be provided.</remarks>
public string? RulesetFilePath { get; set; }
/// <summary>
/// Gets or sets a value indicating whether execution should run in dry-run mode.
/// </summary>
public bool DryRun { get; set; }
/// <summary>
/// Gets or sets input parser flags.
/// </summary>
public NftInputFlags InputFlags { get; set; }
/// <summary>
/// Gets or sets output behavior flags.
/// </summary>
public NftOutputFlags OutputFlags { get; set; }
/// <summary>
/// Gets or sets debug flags.
/// </summary>
public NftDebugLevel DebugFlags { get; set; }
/// <summary>
/// Gets or sets optimize flags.
/// </summary>
public NftOptimizeFlags OptimizeFlags { get; set; }
/// <summary>
/// Creates a request from command text.
/// </summary>
/// <param name="rulesetText">Ruleset command text.</param>
/// <param name="dryRun">Whether the request should run in dry-run mode.</param>
/// <returns>A configured request instance.</returns>
public static NftApplyRequest FromText(string rulesetText, bool dryRun = false)
=> new() { RulesetText = rulesetText, DryRun = dryRun };
/// <summary>
/// Creates a request from a file path.
/// </summary>
/// <param name="rulesetFilePath">Path to file containing ruleset commands.</param>
/// <param name="dryRun">Whether the request should run in dry-run mode.</param>
/// <returns>A configured request instance.</returns>
public static NftApplyRequest FromFile(string rulesetFilePath, bool dryRun = false)
=> new() { RulesetFilePath = rulesetFilePath, DryRun = dryRun };
}

View File

@@ -0,0 +1,219 @@
using System;
using LibNftables.Bindings.Native;
namespace LibNftables;
/// <summary>
/// Low-level managed wrapper around a native <c>nft_ctx</c>.
/// </summary>
/// <remarks>
/// Use <see cref="NftablesClient"/> for high-level workflows. This type is intended for advanced scenarios
/// requiring direct control over context flags and command execution.
/// </remarks>
public sealed class NftContext : IDisposable
{
private SWIGTYPE_p_nft_ctx? _ctx;
/// <summary>
/// Initializes a new context instance.
/// </summary>
/// <param name="contextFlags">Native context flags passed to <c>nft_ctx_new</c>.</param>
/// <exception cref="InvalidOperationException">Thrown when native context creation fails.</exception>
public NftContext(uint contextFlags = 0)
{
_ctx = libnftables.nft_ctx_new(contextFlags);
if (_ctx is null)
{
throw new InvalidOperationException("Failed to create nftables context.");
}
}
/// <summary>
/// Finalizes the context if it was not explicitly disposed.
/// </summary>
~NftContext()
{
Dispose(disposing: false);
}
/// <summary>
/// Gets or sets a value indicating whether command execution runs in dry-run mode.
/// </summary>
public bool DryRun
{
get => libnftables.nft_ctx_get_dry_run(Handle);
set => libnftables.nft_ctx_set_dry_run(Handle, value);
}
/// <summary>
/// Gets or sets optimization flags.
/// </summary>
public NftOptimizeFlags OptimizeFlags
{
get => (NftOptimizeFlags)libnftables.nft_ctx_get_optimize(Handle);
set => libnftables.nft_ctx_set_optimize(Handle, (uint)value);
}
/// <summary>
/// Gets or sets parser input flags.
/// </summary>
public NftInputFlags InputFlags
{
get => (NftInputFlags)libnftables.nft_ctx_input_get_flags(Handle);
set => _ = libnftables.nft_ctx_input_set_flags(Handle, (uint)value);
}
/// <summary>
/// Gets or sets output formatting and behavior flags.
/// </summary>
public NftOutputFlags OutputFlags
{
get => (NftOutputFlags)libnftables.nft_ctx_output_get_flags(Handle);
set => libnftables.nft_ctx_output_set_flags(Handle, (uint)value);
}
/// <summary>
/// Gets or sets debug output flags.
/// </summary>
public NftDebugLevel DebugFlags
{
get => (NftDebugLevel)libnftables.nft_ctx_output_get_debug(Handle);
set => libnftables.nft_ctx_output_set_debug(Handle, (uint)value);
}
/// <summary>
/// Enables in-memory buffering for standard command output.
/// </summary>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void BufferOutput() => EnsureSuccess(libnftables.nft_ctx_buffer_output(Handle), nameof(BufferOutput));
/// <summary>
/// Disables in-memory buffering for standard command output.
/// </summary>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void UnbufferOutput() => EnsureSuccess(libnftables.nft_ctx_unbuffer_output(Handle), nameof(UnbufferOutput));
/// <summary>
/// Gets buffered standard command output.
/// </summary>
/// <returns>Buffered output, or <see langword="null"/> when unavailable.</returns>
public string? GetOutputBuffer() => libnftables.nft_ctx_get_output_buffer(Handle);
/// <summary>
/// Enables in-memory buffering for error output.
/// </summary>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void BufferError() => EnsureSuccess(libnftables.nft_ctx_buffer_error(Handle), nameof(BufferError));
/// <summary>
/// Disables in-memory buffering for error output.
/// </summary>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void UnbufferError() => EnsureSuccess(libnftables.nft_ctx_unbuffer_error(Handle), nameof(UnbufferError));
/// <summary>
/// Gets buffered error output.
/// </summary>
/// <returns>Buffered error output, or <see langword="null"/> when unavailable.</returns>
public string? GetErrorBuffer() => libnftables.nft_ctx_get_error_buffer(Handle);
/// <summary>
/// Adds an include search path.
/// </summary>
/// <param name="path">Filesystem include path.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="path"/> is null, empty, or whitespace.</exception>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void AddIncludePath(string path)
{
ArgumentException.ThrowIfNullOrWhiteSpace(path);
EnsureSuccess(libnftables.nft_ctx_add_include_path(Handle, path), nameof(AddIncludePath));
}
/// <summary>
/// Clears all include search paths currently configured on this context.
/// </summary>
public void ClearIncludePaths() => libnftables.nft_ctx_clear_include_paths(Handle);
/// <summary>
/// Adds a variable expression.
/// </summary>
/// <param name="variableExpression">Variable definition text understood by nftables parser.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="variableExpression"/> is null, empty, or whitespace.</exception>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void AddVariable(string variableExpression)
{
ArgumentException.ThrowIfNullOrWhiteSpace(variableExpression);
EnsureSuccess(libnftables.nft_ctx_add_var(Handle, variableExpression), nameof(AddVariable));
}
/// <summary>
/// Clears all variables currently configured on this context.
/// </summary>
public void ClearVariables() => libnftables.nft_ctx_clear_vars(Handle);
/// <summary>
/// Executes one or more nft commands from text.
/// </summary>
/// <param name="commandText">Command text.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="commandText"/> is null, empty, or whitespace.</exception>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void RunCommand(string commandText)
{
ArgumentException.ThrowIfNullOrWhiteSpace(commandText);
EnsureSuccess(libnftables.nft_run_cmd_from_buffer(Handle, commandText), nameof(RunCommand));
}
/// <summary>
/// Executes nft commands loaded from a file.
/// </summary>
/// <param name="path">Path to the command file.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="path"/> is null, empty, or whitespace.</exception>
/// <exception cref="NftException">Thrown when native operation fails.</exception>
public void RunCommandFromFile(string path)
{
ArgumentException.ThrowIfNullOrWhiteSpace(path);
EnsureSuccess(libnftables.nft_run_cmd_from_filename(Handle, path), nameof(RunCommandFromFile));
}
/// <summary>
/// Releases native resources associated with this context.
/// </summary>
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);
}
}

View File

@@ -0,0 +1,68 @@
namespace LibNftables;
/// <summary>
/// Indicates native runtime loading or initialization failed.
/// </summary>
public sealed class NftNativeLoadException : NftException
{
/// <summary>
/// Initializes a new instance of the <see cref="NftNativeLoadException"/> class.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="innerException">Optional inner exception.</param>
public NftNativeLoadException(string message, Exception? innerException = null)
: base(message, nativeErrorCode: 0, nativeErrorOutput: null, innerException)
{
}
}
/// <summary>
/// Indicates insufficient privileges for requested operation.
/// </summary>
public sealed class NftPermissionException : NftException
{
/// <summary>
/// Initializes a new instance of the <see cref="NftPermissionException"/> class.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="nativeErrorCode">Native error code.</param>
/// <param name="nativeErrorOutput">Native error output.</param>
public NftPermissionException(string message, int nativeErrorCode, string? nativeErrorOutput)
: base(message, nativeErrorCode, nativeErrorOutput)
{
}
}
/// <summary>
/// Indicates invalid request input or invalid nft command/ruleset syntax.
/// </summary>
public sealed class NftValidationException : NftException
{
/// <summary>
/// Initializes a new instance of the <see cref="NftValidationException"/> class.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="nativeErrorCode">Native error code.</param>
/// <param name="nativeErrorOutput">Native error output.</param>
public NftValidationException(string message, int nativeErrorCode, string? nativeErrorOutput)
: base(message, nativeErrorCode, nativeErrorOutput)
{
}
}
/// <summary>
/// Indicates an unsupported feature, platform, or runtime condition.
/// </summary>
public sealed class NftUnsupportedException : NftException
{
/// <summary>
/// Initializes a new instance of the <see cref="NftUnsupportedException"/> class.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="nativeErrorCode">Native error code.</param>
/// <param name="nativeErrorOutput">Native error output.</param>
public NftUnsupportedException(string message, int nativeErrorCode = 0, string? nativeErrorOutput = null)
: base(message, nativeErrorCode, nativeErrorOutput)
{
}
}

112
src/LibNftables/NftEnums.cs Normal file
View File

@@ -0,0 +1,112 @@
using System;
namespace LibNftables;
/// <summary>
/// Optimization flags for native nftables context.
/// </summary>
[Flags]
public enum NftOptimizeFlags : uint
{
/// <summary>No optimization flags.</summary>
None = 0,
/// <summary>Enables optimization.</summary>
Enabled = 0x1,
}
/// <summary>
/// Input parser flags.
/// </summary>
[Flags]
public enum NftInputFlags : uint
{
/// <summary>No input flags.</summary>
None = 0,
/// <summary>Disable DNS lookups while parsing input.</summary>
NoDns = 1u << 0,
/// <summary>Interpret input as JSON.</summary>
Json = 1u << 1,
}
/// <summary>
/// Output formatting and behavior flags.
/// </summary>
[Flags]
public enum NftOutputFlags : uint
{
/// <summary>No output flags.</summary>
None = 0,
/// <summary>Enable reverse DNS names.</summary>
ReverseDns = 1u << 0,
/// <summary>Enable service name rendering.</summary>
Service = 1u << 1,
/// <summary>Enable stateless rendering mode.</summary>
Stateless = 1u << 2,
/// <summary>Show object handles.</summary>
Handle = 1u << 3,
/// <summary>Emit JSON output.</summary>
Json = 1u << 4,
/// <summary>Echo commands in output.</summary>
Echo = 1u << 5,
/// <summary>Show GUID values.</summary>
Guid = 1u << 6,
/// <summary>Use numeric protocol identifiers.</summary>
NumericProto = 1u << 7,
/// <summary>Use numeric priority values.</summary>
NumericPrio = 1u << 8,
/// <summary>Use numeric symbol values.</summary>
NumericSymbol = 1u << 9,
/// <summary>Use numeric time values.</summary>
NumericTime = 1u << 10,
/// <summary>Enable all numeric output flags.</summary>
NumericAll = NumericProto | NumericPrio | NumericSymbol | NumericTime,
/// <summary>Enable terse output format.</summary>
Terse = 1u << 11,
}
/// <summary>
/// Debug output flags.
/// </summary>
[Flags]
public enum NftDebugLevel : uint
{
/// <summary>No debug flags.</summary>
None = 0,
/// <summary>Scanner debugging.</summary>
Scanner = 0x1,
/// <summary>Parser debugging.</summary>
Parser = 0x2,
/// <summary>Evaluation debugging.</summary>
Evaluation = 0x4,
/// <summary>Netlink debugging.</summary>
Netlink = 0x8,
/// <summary>libmnl debugging.</summary>
Mnl = 0x10,
/// <summary>Protocol context debugging.</summary>
ProtoContext = 0x20,
/// <summary>Segment tree debugging.</summary>
Segtree = 0x40,
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,33 @@
using System;
namespace LibNftables;
/// <summary>
/// Base exception for managed nftables failures.
/// </summary>
public class NftException : InvalidOperationException
{
/// <summary>
/// Initializes a new exception instance.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="nativeErrorCode">Native error code, when available.</param>
/// <param name="nativeErrorOutput">Native error output, when available.</param>
/// <param name="innerException">Optional inner exception.</param>
public NftException(string message, int nativeErrorCode = 0, string? nativeErrorOutput = null, Exception? innerException = null)
: base(message, innerException)
{
NativeErrorCode = nativeErrorCode;
NativeErrorOutput = nativeErrorOutput;
}
/// <summary>
/// Gets the native error code.
/// </summary>
public int NativeErrorCode { get; }
/// <summary>
/// Gets native error output text.
/// </summary>
public string? NativeErrorOutput { get; }
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,8 @@
namespace LibNftables;
/// <summary>
/// Represents an exported nftables ruleset snapshot.
/// </summary>
/// <param name="RulesetText">Captured ruleset text.</param>
/// <param name="CapturedAtUtc">Capture timestamp in UTC.</param>
public sealed record NftSnapshot(string RulesetText, System.DateTimeOffset CapturedAtUtc);

View File

@@ -0,0 +1,9 @@
namespace LibNftables;
/// <summary>
/// Represents the outcome of ruleset validation.
/// </summary>
/// <param name="IsValid">Indicates whether validation succeeded.</param>
/// <param name="Output">Captured standard output, when available.</param>
/// <param name="Diagnostics">Validation diagnostics or error output, when available.</param>
public sealed record NftValidationResult(bool IsValid, string? Output, string? Diagnostics);

View File

@@ -0,0 +1,179 @@
using System.Threading;
using System.Threading.Tasks;
namespace LibNftables;
/// <summary>
/// Default high-level nftables client implementation.
/// </summary>
/// <remarks>
/// This client wraps <see cref="NftContext"/> and applies a command-centric workflow:
/// validate (dry-run), apply, snapshot, and restore.
/// </remarks>
public sealed class NftablesClient : INftablesClient
{
private readonly NftablesClientOptions _options;
private readonly System.Func<NftContext> _contextFactory;
/// <summary>
/// Initializes a new instance of the <see cref="NftablesClient"/> class.
/// </summary>
/// <param name="options">Optional client options.</param>
/// <exception cref="NftUnsupportedException">Thrown when runtime/platform is unsupported.</exception>
/// <exception cref="NftNativeLoadException">Thrown when required native runtime components cannot be loaded.</exception>
public NftablesClient(NftablesClientOptions? options = null)
: this(options, static () => new NftContext())
{
}
internal NftablesClient(NftablesClientOptions? options, System.Func<NftContext> contextFactory)
{
_options = options ?? new NftablesClientOptions();
_contextFactory = contextFactory;
NftRuntimeGuard.EnsureInitializedForLinuxX64();
}
/// <inheritdoc />
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);
}
}
/// <inheritdoc />
public Task<NftValidationResult> ValidateAsync(NftApplyRequest request, CancellationToken ct = default)
=> Task.FromResult(Validate(request, ct));
/// <inheritdoc />
public void Apply(NftApplyRequest request, CancellationToken ct = default)
{
ct.ThrowIfCancellationRequested();
ValidateRequest(request);
_ = Execute(request, forceDryRun: null, ct);
}
/// <inheritdoc />
public Task ApplyAsync(NftApplyRequest request, CancellationToken ct = default)
{
Apply(request, ct);
return Task.CompletedTask;
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public Task<NftSnapshot> SnapshotAsync(CancellationToken ct = default)
=> Task.FromResult(Snapshot(ct));
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}

View File

@@ -0,0 +1,42 @@
namespace LibNftables;
/// <summary>
/// Configures default behavior for <see cref="NftablesClient"/>.
/// </summary>
public sealed class NftablesClientOptions
{
/// <summary>
/// Gets or sets default input flags applied to each request.
/// </summary>
public NftInputFlags DefaultInputFlags { get; set; }
/// <summary>
/// Gets or sets default output flags applied to each request.
/// </summary>
public NftOutputFlags DefaultOutputFlags { get; set; }
/// <summary>
/// Gets or sets default debug flags applied to each request.
/// </summary>
public NftDebugLevel DefaultDebugFlags { get; set; }
/// <summary>
/// Gets or sets default optimize flags applied to each request.
/// </summary>
public NftOptimizeFlags DefaultOptimizeFlags { get; set; }
/// <summary>
/// Gets or sets a value indicating whether output buffering is enabled automatically.
/// </summary>
public bool BufferOutput { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether error buffering is enabled automatically.
/// </summary>
public bool BufferError { get; set; } = true;
/// <summary>
/// Gets or sets command text used for snapshot capture.
/// </summary>
public string SnapshotCommandText { get; set; } = "list ruleset";
}

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\LibNftables\LibNftables.csproj" />
</ItemGroup>
</Project>

View File

@@ -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<NftException>(() => 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;
}
}
}

View File

@@ -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));
}
}

View File

@@ -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<NftValidationException>(() => 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<NftValidationException>(() => 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.
}
}
}