Skip to content

npcap to work with similar behavior as WinPcap #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: fullManaged
Choose a base branch
from
Open
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: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ PcapDotNet/src/TestResults
PcapDotNet.DevelopersPack/3rdParty/
artifacts/
.vs/
.idea/
.vscode/
TemporaryGeneratedFile_*
*.cache
*.csproj.FileListAbsolute.txt
Expand All @@ -15,6 +17,6 @@ TemporaryGeneratedFile_*
*.pdb
*.sdf
*.suo
*.vcxproj.user
*.user
*.db
*.opendb
20 changes: 3 additions & 17 deletions PcapDotNet/src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,22 @@
<AppendTargetFrameworkToOutputPath>True</AppendTargetFrameworkToOutputPath>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<IsPackable>False</IsPackable>
<TargetFrameworks>net40;net80</TargetFrameworks>
</PropertyGroup>

<!-- All none test projects -->
<Choose>
<When Condition=" !$(MSBuildProjectName.EndsWith('.Test')) ">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)PcapDotNet.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
</When>
</Choose>

<!-- All test projects -->
<Choose>
<When Condition=" $(MSBuildProjectName.EndsWith('.TestUtils')) ">
<Otherwise>
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>
</When>
</Choose>

<Choose>
<When Condition=" $(MSBuildProjectName.EndsWith('.Test')) ">
<PropertyGroup>
<TargetFrameworks>net48;net8.0</TargetFrameworks>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
</PropertyGroup>
</When>
</Otherwise>
</Choose>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0">
<PackageReference Include="xunit" Version="1.9.2" Condition="'$(TargetFramework)' == 'net40'" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" Condition="'$(TargetFramework)' == 'net40'">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.9.2" Condition="'$(TargetFramework)' == 'net80'" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0" Condition="'$(TargetFramework)' == 'net80'">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
4 changes: 2 additions & 2 deletions PcapDotNet/src/PcapDotNet.Base.Test/UInt128Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void CastToULongOverflow()
}
catch (Exception)
{
Assert.Fail();
Assert.False(true);
return;
}
Assert.Equal(overflow, (ulong)value);
Expand Down Expand Up @@ -251,4 +251,4 @@ public void ToStringTestFirstBitIsOne()
Assert.Equal(ValueString, value.ToString("x32"));
}
}
}
}
5 changes: 3 additions & 2 deletions PcapDotNet/src/PcapDotNet.Base/IListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace PcapDotNet.Base
public static class IListExtensions
// ReSharper restore InconsistentNaming
{
#if !NET7_0_OR_GREATER
/// <summary>
/// Wraps a list with a ReadOnlyCollection.
/// </summary>
Expand All @@ -21,7 +22,7 @@ public static ReadOnlyCollection<T> AsReadOnly<T>(this IList<T> list)
{
return new ReadOnlyCollection<T>(list);
}

#endif
/// <summary>
/// Returns an enumerable of all the elements in the given list starting in a specific offset and taking no more than a specific count.
/// </summary>
Expand All @@ -37,4 +38,4 @@ public static IEnumerable<T> Range<T>(this IList<T> list, int offset, int count)
yield return list[i];
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Management;
using System.Net.NetworkInformation;
using Microsoft.Win32;
using PcapDotNet.Core.Native;
using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet;

Expand Down Expand Up @@ -31,6 +32,8 @@ public static string GetGuid(this LivePacketDevice livePacketDevice)
throw new ArgumentNullException("livePacketDevice");

string livePacketDeviceName = livePacketDevice.Name;
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
return livePacketDeviceName;
if (!livePacketDeviceName.StartsWith(NamePrefix, StringComparison.Ordinal))
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
Expand All @@ -50,11 +53,14 @@ public static string GetGuid(this LivePacketDevice livePacketDevice)
/// <exception cref="InvalidOperationException">When the PNPDeviceID cannot be retrieved from the registry.</exception>
public static string GetPnpDeviceId(this LivePacketDevice livePacketDevice)
{
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
throw new InvalidOperationException("Platform not supported");

string guid = livePacketDevice.GetGuid();

using (RegistryKey key = Registry.LocalMachine.OpenSubKey(NetworkConnectionConfigKey + @"\" + guid + @"\Connection"))
{
string pnpDeviceId = key.GetValue("PnpInstanceID") as string;
string pnpDeviceId = key?.GetValue("PnpInstanceID") as string;
if (pnpDeviceId == null)
throw new InvalidOperationException("Could not find PNP Device ID in the registry");
return pnpDeviceId;
Expand All @@ -75,7 +81,7 @@ public static NetworkInterface GetNetworkInterface(this LivePacketDevice livePac
throw new ArgumentNullException("livePacketDevice");

string guid = GetGuid(livePacketDevice);
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(networkInterface => networkInterface.Id == guid);
return Interop.Pcap.GetAllNetworkInterfacesByDotNet().FirstOrDefault(networkInterface => networkInterface.Id == guid);
}

/// <summary>
Expand All @@ -95,6 +101,12 @@ public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice)
return new MacAddress(addressBytes.ReadUInt48(0, Endianity.Big));
}

if (Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX
&& livePacketDevice.Name == "rpcap://\\Device\\NPF_Loopback")
{
return new MacAddress();
}

return livePacketDevice.GetMacAddressWmi();
}

Expand All @@ -107,6 +119,9 @@ public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice)
/// <exception cref="InvalidOperationException">When the <see cref="MacAddress"/> cannot be retrieved using WMI.</exception>
private static MacAddress GetMacAddressWmi(this LivePacketDevice livePacketDevice)
{
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
throw new InvalidOperationException("No MAC Address on device: " + livePacketDevice.Name);

string pnpDeviceId = livePacketDevice.GetPnpDeviceId();
string escapedPnpDeviceId = pnpDeviceId.Replace(@"\", @"\\");

Expand All @@ -128,4 +143,4 @@ private static MacAddress GetMacAddressWmi(this LivePacketDevice livePacketDevic
throw new InvalidOperationException("No MAC Address for WMI instance with PNP Device ID: " + pnpDeviceId);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;

namespace PcapDotNet.Core.Extensions
{
Expand All @@ -21,7 +22,9 @@ public static LivePacketDevice GetLivePacketDevice(this NetworkInterface network
if (networkInterface == null)
throw new ArgumentNullException("networkInterface");

return LivePacketDevice.AllLocalMachine.FirstOrDefault(device => device.Name == LivePacketDeviceExtensions.NamePrefix + networkInterface.Id);
return LivePacketDevice.AllLocalMachine.FirstOrDefault(device => Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX
? device.Name == networkInterface.Id
: device.Name == LivePacketDeviceExtensions.NamePrefix + networkInterface.Id);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.Management" Version="8.0.0" />
<Reference Include="System.Management" />
</ItemGroup>

</Project>
<ItemGroup>
<PackageReference Include="System.Management" Version="8.0.0" Condition="'$(TargetFramework)' == 'net80'" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions PcapDotNet/src/PcapDotNet.Core.Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace PcapDotNet.Core.Extensions
{
/// <summary>
/// Extension methods for Task class.
/// </summary>
public static class TaskExtensions
{
/// <summary>
/// Creates a Task that will complete after a time delay.
/// </summary>
/// <param name="delay">The time span to wait before completing the returned Task</param>
/// <returns>A Task that represents the time delay</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The <paramref name="delay"/> is less than -1 or greater than the maximum allowed timer duration.
/// </exception>
/// <remarks>
/// After the specified time delay, the Task is completed in RanToCompletion state.
/// </remarks>
public static Task Delay(TimeSpan delay)
{
// timer inaccuracy https://github.com/dotnet/runtime/issues/100455
#if NETCOREAPP1_0_OR_GREATER
return Task.Delay(delay.Add(TimeSpan.FromMilliseconds(1))); // +1 is to workaround, random return less than 1 ms too early
#else
var tcs = new TaskCompletionSource<object>();
Timer timer = null;
timer = new Timer(_ =>
{
tcs.SetResult(null);
timer.Dispose(); // prevent GC
});
timer.Change((long)delay.TotalMilliseconds + 1, -1); // +1 is to workaround, random return less than 1 ms too early
return tcs.Task;
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ namespace PcapDotNet.Core.Test
/// Summary description for BerkeleyPacketFilterTests
/// </summary>
[ExcludeFromCodeCoverage]
[Collection(nameof(LivePacketDeviceTests))]
public class BerkeleyPacketFilterTests
{
#if !REAL
public BerkeleyPacketFilterTests()
{
TestablePcapPal.UseTestPal();
}
#endif

[Fact]
public void BadFilterErrorTest()
{
Expand All @@ -22,6 +28,7 @@ public void BadFilterErrorTest()
}
}

// fails on REAL unix because no packets are sent
[Fact]
public void NoCommunicatorConstructorTest()
{
Expand All @@ -41,6 +48,7 @@ public void NoCommunicatorConstructorTest()
}
}

// fails on REAL unix because no packets are sent
[Fact]
public void NoCommunicatorConstructorWithNetmaskTest()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using PcapDotNet.Core.Extensions;
using Xunit;

Expand All @@ -9,24 +10,47 @@ namespace PcapDotNet.Core.Test
/// Summary description for LivePacketDeviceExtensionsTests
/// </summary>
[ExcludeFromCodeCoverage]
[Collection(nameof(LivePacketDeviceTests))]
public class LivePacketDeviceExtensionsTests
{
#if !REAL
public LivePacketDeviceExtensionsTests()
{
TestablePcapPal.UseTestPal();
}
#endif

[Fact]
public void GetNetworkInterfaceNullTest()
{
Assert.Throws<ArgumentNullException>(() => LivePacketDeviceExtensions.GetNetworkInterface(null));
}

[Fact(Skip ="NullRefExcetion for loopback device")]

// this test tests on linux other paths!
[Fact]
public void GetMacAddressTest()
{
foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine)
{
_ = device.GetMacAddress();
if ((Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
&& (device.Name == "any" || device.Name == "bluetooth-monitor" || device.Name == "nflog"
|| device.Name == "nfqueue" || device.Name == "dbus-system" || device.Name == "dbus-session"))
{
continue;
}

_ = device.GetMacAddress();
}
}

// this test tests on linux other paths!
[Fact]
public void GetMacAddress_Loopback_ReturnsZeroMac()
{
var loopback = LivePacketDevice.AllLocalMachine.First(n => (n.Attributes & DeviceAttributes.Loopback) != 0);

Assert.Equal(Packets.Ethernet.MacAddress.Zero, loopback.GetMacAddress());
}

[Fact]
public void GetGuidNullDeviceTest()
{
Expand Down
Loading