Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

This repository contains a .NET 10 solution for working with Linux iptables from C#. The managed code lives under `IPTables.Net/`, the NUnit tests live under `IPTables.Net.Tests/`, and the native helper library used by the libiptc-based adapter lives under `ipthelper/`.
This repository contains a .NET 10 solution for working with Linux iptables from C#. The managed code lives under `IPTables.Net/`, the xUnit tests live under `IPTables.Net.Tests/`, and the native helper library used by the libiptc-based adapter lives under `ipthelper/`.

## Build And Test

Expand Down Expand Up @@ -31,7 +31,7 @@ Both scripts will bootstrap a usable .NET SDK if `dotnet` is missing. By default

## Development Guidance

- Keep changes narrow and add or update NUnit coverage in `IPTables.Net.Tests/` when behavior changes.
- Keep changes narrow and add or update xUnit coverage in `IPTables.Net.Tests/` when behavior changes.
- Prefer following the existing project layout instead of introducing new abstractions unless the current design is clearly blocking the work.
- When changing native interop behavior, verify both the managed call sites in `IPTables.Net/Iptables/NativeLibrary/` and the corresponding code in `ipthelper/`.
- The tests project is also the best source of usage examples for the public API.
17 changes: 11 additions & 6 deletions IPTables.Net.TestFramework/IPTables.Net.TestFramework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\IPTables.Net\IPTables.Net.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="NUnit" Version="3.12.0" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\IPTables.Net\IPTables.Net.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="xunit.v3.assert" Version="3.2.2" />
</ItemGroup>
</Project>
3 changes: 1 addition & 2 deletions IPTables.Net.TestFramework/MockIpsetSystemFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using SystemInteract;
using IPTables.Net.IpSet;
using NUnit.Framework;

namespace IPTables.Net.TestFramework
{
Expand All @@ -31,7 +30,7 @@ public void TestSync(IpSetSets rulesNew, List<string> expectedCommands)
{
TestSync(rulesNew);

CollectionAssert.AreEqual(expectedCommands, Commands.Select(a => a.Value).ToList());
Assert.Equal(expectedCommands, Commands.Select(a => a.Value).ToList());
}
}
}
3 changes: 1 addition & 2 deletions IPTables.Net.TestFramework/MockIptablesSystemFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using IPTables.Net.Iptables;
using IPTables.Net.Iptables.Adapter.Client;
using IPTables.Net.Iptables.TableSync;
using NUnit.Framework;

namespace IPTables.Net.TestFramework
{
Expand Down Expand Up @@ -57,7 +56,7 @@ public void TestSync<TSync>(IIPTablesAdapterClient client, IpTablesRuleSet rules

if (expectedCommands != null)
{
CollectionAssert.AreEqual(expectedCommands, ExecutionLog.Select(a => a.Value).ToList());
Assert.Equal(expectedCommands, ExecutionLog.Select(a => a.Value).ToList());
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions IPTables.Net.Tests/CheckDebugComparison.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
using IPTables.Net.Iptables.Modules.HashLimit;
using NUnit.Framework;
using System;
using System.Linq;
using IPTables.Net.Iptables;
using static IPTables.Net.Iptables.IpTablesRule;

namespace IPTables.Net.Tests
{
[TestFixture]
public class CheckDebugComparison
{
[TestCase]
[Fact]
public void TestHashLimitMemberProperties()
{
var hl = new HashLimitModule(4);
Expand Down
8 changes: 3 additions & 5 deletions IPTables.Net.Tests/CheckInternalTables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
using System.Linq;
using System.Text;
using IPTables.Net.Iptables;
using NUnit.Framework;

namespace IPTables.Net.Tests
{
[TestFixture]
class CheckInternalTables
public class CheckInternalTables
{
[Test]
[Fact]
public void TestChains()
{
TestChain("filter", "INPUT");
Expand All @@ -33,7 +31,7 @@ public void TestChains()

private void TestChain(string table, string chain)
{
Assert.IsTrue(IPTablesTables.IsInternalChain(table, chain), String.Format("{0}:{1} should be internal", table, chain));
Assert.True(IPTablesTables.IsInternalChain(table, chain), String.Format("{0}:{1} should be internal", table, chain));
}
}
}
68 changes: 25 additions & 43 deletions IPTables.Net.Tests/ConntrackLibraryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,44 @@
using IPTables.Net.Conntrack;
using IPTables.Net.Iptables.NativeLibrary;
using IPTables.Net.Supporting;
using NUnit.Framework;

namespace IPTables.Net.Tests
{
[TestFixture]
[Category("NotWorkingOnTravis")]
class ConntrackLibraryTests
[Trait("Category", "NotWorkingOnTravis")]
public class ConntrackLibraryTests
{
public static bool IsLinux
{
get
{
int p = (int)Environment.OSVersion.Platform;
return (p == 4) || (p == 6) || (p == 128);
}
}

[Test]
[Fact]
public void TestStructureSize()
{
Assert.AreEqual(8 + IntPtr.Size, Marshal.SizeOf(typeof(ConntrackQueryFilter)));
Assert.Equal(8 + IntPtr.Size, Marshal.SizeOf(typeof(ConntrackQueryFilter)));
}

[Test]
[Fact]
public void TestDump()
{
if (IsLinux)
{
if (Environment.GetEnvironmentVariable("SKIP_SYSTEM_TESTS") == "1")
{
Assert.Ignore();
}
ConntrackSystem cts = new ConntrackSystem();
List<byte[]> list = new List<byte[]>();
cts.Dump(false,list.Add);
}
TestEnvironment.RequireLinuxSystemTests();

ConntrackSystem cts = new ConntrackSystem();
List<byte[]> list = new List<byte[]>();
cts.Dump(false, list.Add);
}

[Test]
[Fact]
public void TestDumpFiltered()
{
if (IsLinux)
{
if (Environment.GetEnvironmentVariable("SKIP_SYSTEM_TESTS") == "1")
{
Assert.Ignore();
}
ConntrackSystem cts = new ConntrackSystem();
IPAddress addr = IPAddress.Parse("1.1.1.1");
UInt32 addr32;
unchecked
{
addr32 = (UInt32)addr.ToInt();
}

TestEnvironment.RequireLinuxSystemTests();

ConntrackSystem cts = new ConntrackSystem();
IPAddress addr = IPAddress.Parse("1.1.1.1");
UInt32 addr32;
unchecked
{
addr32 = (UInt32)addr.ToInt();
}

var pinned = GCHandle.Alloc(addr32, GCHandleType.Pinned);
var pinned = GCHandle.Alloc(addr32, GCHandleType.Pinned);
try
{
ConntrackQueryFilter[] qf = new ConntrackQueryFilter[]
{
new ConntrackQueryFilter{Key = cts.GetConstant("CTA_TUPLE_ORIG"), Max = cts.GetConstant("CTA_TUPLE_MAX"), CompareLength = 0},
Expand All @@ -77,7 +57,9 @@ public void TestDumpFiltered()

List<byte[]> list = new List<byte[]>();
cts.Dump(false, list.Add, qf);

}
finally
{
pinned.Free();
}
}
Expand Down
30 changes: 14 additions & 16 deletions IPTables.Net.Tests/EscapeHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,33 @@
using System.Text;
using IPTables.Net.Iptables.Helpers;
using IPTables.Net.Supporting;
using NUnit.Framework;

namespace IPTables.Net.Tests
{
[TestFixture]
class EscapeHelperTests
public class EscapeHelperTests
{
[Test]
[Fact]
public void TestSpaces()
{
Assert.AreEqual("'a word'", ShellHelper.EscapeArguments("a word"));
Assert.AreEqual("singleword", ShellHelper.EscapeArguments("singleword"));
Assert.Equal("'a word'", ShellHelper.EscapeArguments("a word"));
Assert.Equal("singleword", ShellHelper.EscapeArguments("singleword"));
}

[Test]
[Fact]
public void TestPipe()
{
Assert.AreEqual("'|'", ShellHelper.EscapeArguments("|"));
Assert.AreEqual("'a|word'", ShellHelper.EscapeArguments("a|word"));
Assert.AreEqual("singleword", ShellHelper.EscapeArguments("singleword"));
Assert.Equal("'|'", ShellHelper.EscapeArguments("|"));
Assert.Equal("'a|word'", ShellHelper.EscapeArguments("a|word"));
Assert.Equal("singleword", ShellHelper.EscapeArguments("singleword"));
}
[Test]
[Fact]
public void TestSpace()
{
Assert.AreEqual("a word", ShellHelper.BuildArgumentString(new []{"a", "word"}));
Assert.AreEqual("\"two words\"", ShellHelper.BuildArgumentString(new[] { "two words" }));
Assert.AreEqual("\"two words and \\\"punctuation\\\"\"", ShellHelper.BuildArgumentString(new[] { "two words and \"punctuation\"" }));
Assert.AreEqual("bash -c \"bash -c \\\"echo a\\\"\"", ShellHelper.BuildArgumentString(new[] { "bash", "-c", ShellHelper.BuildArgumentString(new []{"bash", "-c", "echo a"}) }));
Assert.AreEqual("bash -c \"bash -c \\\"echo \\\\\\\"a\\\\\\\"\\\"\"", ShellHelper.BuildArgumentString(new[] { "bash", "-c", ShellHelper.BuildArgumentString(new[] { "bash", "-c", "echo \"a\"" }) }));
Assert.Equal("a word", ShellHelper.BuildArgumentString(new []{"a", "word"}));
Assert.Equal("\"two words\"", ShellHelper.BuildArgumentString(new[] { "two words" }));
Assert.Equal("\"two words and \\\"punctuation\\\"\"", ShellHelper.BuildArgumentString(new[] { "two words and \"punctuation\"" }));
Assert.Equal("bash -c \"bash -c \\\"echo a\\\"\"", ShellHelper.BuildArgumentString(new[] { "bash", "-c", ShellHelper.BuildArgumentString(new []{"bash", "-c", "echo a"}) }));
Assert.Equal("bash -c \"bash -c \\\"echo \\\\\\\"a\\\\\\\"\\\"\"", ShellHelper.BuildArgumentString(new[] { "bash", "-c", ShellHelper.BuildArgumentString(new[] { "bash", "-c", "echo \"a\"" }) }));
}
}
}
12 changes: 5 additions & 7 deletions IPTables.Net.Tests/GraphLayoutTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
using IPTables.Net.Iptables.Modules;
using IPTables.Net.Iptables.Modules.Comment;
using IPTables.Net.Tests.MockSystem;
using NUnit.Framework;

namespace IPTables.Net.Tests
{
[TestFixture]
class GraphLayoutTests
public class GraphLayoutTests
{
[Test]
[Fact]
public void TestAddSingles()
{
List<IpCidr> addresses = new List<IpCidr>();
Expand All @@ -29,9 +27,9 @@ public void TestAddSingles()
CidrGraph graph = CidrGraph.BuildGraph(addresses);

//These numbers are based on the best I could do on paper. This less than perfect algorithm can beat that.
Assert.IsTrue(graph.CalculateMaxPathLength() < 20, "Criteria for a good algorithm (max): " + graph.CalculateMaxPathLength());
Assert.IsTrue(graph.CalculateMinPathLength() < 10, "Criteria for a good algorithm (min): " + graph.CalculateMinPathLength());
Assert.IsTrue(graph.CalculateAveragePathLength() < 11, "Criteria for a good algorithm (avg): " + graph.CalculateAveragePathLength());
Assert.True(graph.CalculateMaxPathLength() < 20, "Criteria for a good algorithm (max): " + graph.CalculateMaxPathLength());
Assert.True(graph.CalculateMinPathLength() < 10, "Criteria for a good algorithm (min): " + graph.CalculateMinPathLength());
Assert.True(graph.CalculateAveragePathLength() < 11, "Criteria for a good algorithm (avg): " + graph.CalculateAveragePathLength());
}


Expand Down
12 changes: 10 additions & 2 deletions IPTables.Net.Tests/IPTables.Net.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Remove="GraphLayoutTests.cs" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="SystemInteract.Local" Version="1.1.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="xunit.v3" Version="3.2.2" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 6 additions & 8 deletions IPTables.Net.Tests/IPTablesRuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@
using System.Security.Cryptography;
using IPTables.Net.Iptables;
using IPTables.Net.Iptables.Modules.Mark;
using NUnit.Framework;

namespace IPTables.Net.Tests
{
[TestFixture]
internal class IPTablesRuleTests
public class IPTablesRuleTests
{
[Test]
[Fact]
public void TestDefaultChain()
{
IpTablesChainSet chains = new IpTablesChainSet(4);
var rule = IpTablesRule.Parse("-A PREROUTING -s 1.1.1.1 -j TEST", null, chains, 4, "raw", IpTablesRule.ChainCreateMode.CreateNewChainIfNeeded);
Assert.AreEqual("raw", rule.Chain.Table);
Assert.Equal("raw", rule.Chain.Table);
}

[Test]
[Fact]
public void TestAppendRule()
{
IpTablesChainSet chains = new IpTablesChainSet(4);
var rule = IpTablesRule.Parse("-A PREROUTING -s 1.1.1.1 -j TEST", null, chains, 4, "raw", IpTablesRule.ChainCreateMode.CreateNewChainIfNeeded);
rule.AppendToRule("! -m devgroup --src-group 0x2");
}

[Test]
[Fact]
public void TestGetModuleOrLoad_CanLoadBareTargetAfterParse()
{
IpTablesChainSet chains = new IpTablesChainSet(4);
Expand All @@ -35,7 +33,7 @@ public void TestGetModuleOrLoad_CanLoadBareTargetAfterParse()

Assert.NotNull(mark);
mark.SetOrMark(1);
Assert.AreEqual("-A INPUT -j MARK --set-xmark 0x1/0x1", rule.GetActionCommand());
Assert.Equal("-A INPUT -j MARK --set-xmark 0x1/0x1", rule.GetActionCommand());
}
}
}
Loading
Loading