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
79 changes: 79 additions & 0 deletions IPTables.Net.Tests/IptcInterfaceTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using IPTables.Net.Iptables.NativeLibrary;

namespace IPTables.Net.Tests
Expand Down Expand Up @@ -58,6 +59,46 @@
[Collection(SystemIptablesCollectionDefinition.Name)]
public class IptcInterfaceTest : IClassFixture<IptcInterfaceFixture>
{
[StructLayout(LayoutKind.Sequential)]
private struct NativeIptIp
{
public uint Source;
public uint Destination;
public uint SourceMask;
public uint DestinationMask;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] InputInterface;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] OutputInterface;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] InputInterfaceMask;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] OutputInterfaceMask;

public ushort Protocol;
public byte Flags;
public byte InverseFlags;
}

[StructLayout(LayoutKind.Sequential)]
private struct NativeIptEntry
{
public NativeIptIp Ip;
public uint Cache;
public ushort TargetOffset;
public ushort NextOffset;
public uint ComeFrom;
public ulong PacketCount;
public ulong ByteCount;
}

private const int XtEntryMatchNameOffset = sizeof(ushort);
private const int XtEntryMatchRevisionOffset = sizeof(ushort) + 29;

private readonly IptcInterfaceFixture _fixture;

public IptcInterfaceTest(IptcInterfaceFixture fixture)
Expand All @@ -74,7 +115,7 @@
using (var iptc = new IptcInterface("filter", _fixture.IpVersion))
{
var rules = iptc.GetRules("test");
Assert.Equal(1, rules.Count);

Check warning on line 118 in IPTables.Net.Tests/IptcInterfaceTest.cs

View workflow job for this annotation

GitHub Actions / build-ubuntu-latest

Do not use Assert.Equal() to check for collection size. Use Assert.Single instead. (https://xunit.net/xunit.analyzers/rules/xUnit2013)
Assert.Equal("-A test -j ACCEPT", iptc.GetRuleString("test", rules[0]));
}
Assert.Equal(0, IptcInterface.RefCount);
Expand Down Expand Up @@ -119,6 +160,44 @@
Assert.Equal(0, IptcInterface.RefCount);
}

[Fact]
public void TestCommitReportsIncompatibleMatchRevision()
{
_fixture.SkipIfNeeded();

Assert.Equal(4, _fixture.IpVersion);
Assert.Equal(0, IptcInterface.RefCount);

using (var iptc = new IptcInterface("filter", _fixture.IpVersion))
{
const string command = "iptables -A test2 -p tcp -m tcp --dport 8081 -j ACCEPT";
Assert.Equal(1, iptc.ExecuteCommand("iptables -A test2 -j test3"));
Assert.Equal(1, iptc.ExecuteCommand(command));

var rules = iptc.GetRules("test2");
Assert.Equal(2, rules.Count);

var match = IntPtr.Add(rules[1], Marshal.SizeOf<NativeIptEntry>());
Assert.Equal("tcp", Marshal.PtrToStringAnsi(IntPtr.Add(match, XtEntryMatchNameOffset)));
Marshal.WriteByte(match, XtEntryMatchRevisionOffset, byte.MaxValue);

Assert.False(iptc.Commit());
Assert.NotEqual(0, iptc.GetLastError());

var error = iptc.GetErrorString();
Assert.Contains("incompatible match \"tcp\" revision 255", error);
Assert.Contains("chain \"test2\", rule 2", error);
Assert.DoesNotContain("(0)", error);
}

Assert.NotEqual(0,
IptablesSystemTestSupport.Execute(_fixture.GetBinary(), "-C test2 -j test3", false));
Assert.NotEqual(0,
IptablesSystemTestSupport.Execute(_fixture.GetBinary(),
"-C test2 -p tcp -m tcp --dport 8081 -j ACCEPT", false));
Assert.Equal(0, IptcInterface.RefCount);
}

[Fact]
public void TestRuleIp()
{
Expand Down
42 changes: 32 additions & 10 deletions IPTables.Net/Iptables/NativeLibrary/IptcInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using IPTables.Net.Exceptions;
using Serilog;

Expand Down Expand Up @@ -388,6 +389,12 @@ public static extern int ip6tc_set_counter(
[DllImport(Helper, SetLastError = true)]
public static extern int execute_command6(string command, IntPtr h);

[DllImport(Helper, SetLastError = true, CharSet = CharSet.Ansi)]
private static extern int commit_handle4(IntPtr h, StringBuilder diagnostic, UIntPtr diagnosticLength);

[DllImport(Helper, SetLastError = true, CharSet = CharSet.Ansi)]
private static extern int commit_handle6(IntPtr h, StringBuilder diagnostic, UIntPtr diagnosticLength);

[DllImport(Helper, SetLastError = true)]
public static extern int init_helper4();

Expand Down Expand Up @@ -516,6 +523,8 @@ public void Dispose()
private List<string> _debugEntries = new List<string>();
private ILogger logger;
private int _ipVersion;
private int? _lastCommitError;
private string _lastCommitDiagnostic;

private void DebugEntry(string message)
{
Expand All @@ -542,6 +551,8 @@ public void OpenTable(string table)
{
if (_handle != IntPtr.Zero)
throw new IpTablesNetException("A table is already open, commit or discard first");
_lastCommitError = null;
_lastCommitDiagnostic = null;
if (_ipVersion == 4)
_handle = init_handle4(table);
else
Expand Down Expand Up @@ -596,7 +607,7 @@ public List<string> GetChains()

public int GetLastError()
{
return Marshal.GetLastWin32Error();
return _lastCommitError ?? Marshal.GetLastWin32Error();
}

public string GetErrorString()
Expand All @@ -607,7 +618,10 @@ public string GetErrorString()
error = iptc_strerror(lastError);
else
error = ip6tc_strerror(lastError);
return string.Format("({0}) {1}", lastError, Marshal.PtrToStringAnsi(error));
var message = string.Format("({0}) {1}", lastError, Marshal.PtrToStringAnsi(error));
if (!string.IsNullOrWhiteSpace(_lastCommitDiagnostic))
message += "; " + _lastCommitDiagnostic;
return message;
}


Expand Down Expand Up @@ -674,17 +688,25 @@ public bool Commit()
_debugEntries.Clear();
}

bool status;
_lastCommitError = null;
_lastCommitDiagnostic = null;

var diagnostic = new StringBuilder(1024);
int result;
if (_ipVersion == 4)
status = iptc_commit(_handle) == 1;
result = commit_handle4(_handle, diagnostic, new UIntPtr((uint)diagnostic.Capacity));
else
status = ip6tc_commit(_handle) == 1;
result = commit_handle6(_handle, diagnostic, new UIntPtr((uint)diagnostic.Capacity));

var commitError = Marshal.GetLastWin32Error();
_handle = IntPtr.Zero;

bool status = result == 1;
if (!status)
Free();
else
//Commit includes free
_handle = IntPtr.Zero;
{
_lastCommitError = commitError;
_lastCommitDiagnostic = diagnostic.ToString();
}
return status;
}

Expand Down Expand Up @@ -737,4 +759,4 @@ public bool FlushChain(string chainName)
return ip6tc_flush_entries(chainName, _handle) == 1;
}
}
}
}
Loading
Loading