Commit cdf717f9 authored by Brickner_cp's avatar Brickner_cp

LivePacketDevice.GetMacAddress() fails for unbound adapter

parent 89ba2830
using System; using System;
using System.Linq; using System.Linq;
using System.Management;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using Microsoft.Win32;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
...@@ -11,6 +13,48 @@ namespace PcapDotNet.Core.Extensions ...@@ -11,6 +13,48 @@ namespace PcapDotNet.Core.Extensions
/// </summary> /// </summary>
public static class LivePacketDeviceExtensions public static class LivePacketDeviceExtensions
{ {
const string NamePrefix = @"rpcap://\Device\NPF_";
const string NetworkConnectionConfigKey = @"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}";
/// <summary>
/// Returns the GUID (NetCfgInstanceId) for a <see cref="LivePacketDevice"/> instance.
/// The GUID is parsed from the <see cref="LivePacketDevice.Name"/> property.
/// </summary>
/// <param name="livePacketDevice">The <see cref="LivePacketDevice"/> instance.</param>
/// <returns>The GUID (NetCfgInstanceId) of the <see cref="LivePacketDevice"/> instance.</returns>
/// <exception cref="InvalidOperationException">When the <see cref="LivePacketDevice.Name"/> doesn't match the expectations.</exception>
public static string GetGuid(this LivePacketDevice livePacketDevice)
{
string livePacketDeviceName = livePacketDevice.Name;
if (!livePacketDeviceName.StartsWith(NamePrefix))
{
throw new InvalidOperationException(string.Format("Invalid LivePacketDevice.Name format: {0} (should start with: {1})",
livePacketDevice.Name, NamePrefix));
}
return livePacketDevice.Name.Substring(NamePrefix.Length);
}
/// <summary>
/// Returns the PNPDeviceID for a <see cref="LivePacketDevice"/> instance.
/// The PNPDeviceID is retrieved by querying the registry.
/// </summary>
/// <param name="livePacketDevice">The <see cref="LivePacketDevice"/> instance.</param>
/// <returns>The PNPDeviceID of the <see cref="LivePacketDevice"/> instance.</returns>
/// <exception cref="InvalidOperationException">When the PNPDeviceID cannot be retrieved from the registry.</exception>
public static string GetPnpDeviceId(this LivePacketDevice livePacketDevice)
{
string guid = livePacketDevice.GetGuid();
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(NetworkConnectionConfigKey + @"\" + guid + @"\Connection"))
{
string pnpDeviceId = key.GetValue("PnpInstanceID") as string;
if (pnpDeviceId == null)
throw new InvalidOperationException("Could not find PNPDeviceID in the registry");
return pnpDeviceId;
}
}
/// <summary> /// <summary>
/// Returns the network interface of the packet device. /// Returns the network interface of the packet device.
/// The interface is found using its id. /// The interface is found using its id.
...@@ -24,23 +68,56 @@ namespace PcapDotNet.Core.Extensions ...@@ -24,23 +68,56 @@ namespace PcapDotNet.Core.Extensions
if (livePacketDevice == null) if (livePacketDevice == null)
throw new ArgumentNullException("livePacketDevice"); throw new ArgumentNullException("livePacketDevice");
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(networkInterface => @"rpcap://\Device\NPF_" + networkInterface.Id == livePacketDevice.Name); string guid = GetGuid(livePacketDevice);
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(networkInterface => networkInterface.Id == guid);
} }
/// <summary> /// <summary>
/// Returns the MacAddress of the network interface of the given device. /// Returns the <see cref="MacAddress"/> of the network interface of the given device.
/// If no interface matches the given packet device, an exception is thrown. /// If no interface matches the given packet device, an exception is thrown.
/// We first look for the device using <see cref="NetworkInterface.GetAllNetworkInterfaces"/> and if that fails we look for them using WMI.
/// </summary> /// </summary>
/// <param name="livePacketDevice">The packet device to look for the matching interface.</param> /// <param name="livePacketDevice">The packet device to look for the matching interface.</param>
/// <returns>The MacAddress of the given device's matching interface.</returns> /// <returns>The <see cref="MacAddress"/> of the given device's matching interface.</returns>
public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice) public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice)
{ {
// First, look for a NetworkInterface
NetworkInterface networkInterface = livePacketDevice.GetNetworkInterface(); NetworkInterface networkInterface = livePacketDevice.GetNetworkInterface();
if (networkInterface == null) if (networkInterface != null)
throw new InvalidOperationException("Couldn't find a network interface for give device"); {
byte[] addressBytes = networkInterface.GetPhysicalAddress().GetAddressBytes();
return new MacAddress(addressBytes.ReadUInt48(0, Endianity.Big));
}
return livePacketDevice.GetMacAddressWmi();
}
/// <summary>
/// Returns the <see cref="MacAddress"/> for a <see cref="LivePacketDevice"/> instance.
/// The <see cref="MacAddress"/> is retrieved through using WMI.
/// </summary>
/// <param name="livePacketDevice">The <see cref="LivePacketDevice"/> instance.</param>
/// <returns>The <see cref="MacAddress"/> of the <see cref="LivePacketDevice"/> instance.</returns>
/// <exception cref="InvalidOperationException">When the <see cref="MacAddress"/> cannot be retrieved using WMI.</exception>
private static MacAddress GetMacAddressWmi(this LivePacketDevice livePacketDevice)
{
string pnpDeviceId = livePacketDevice.GetPnpDeviceId();
string escapedPnpDeviceId = pnpDeviceId.Replace(@"\", @"\\");
ManagementScope scope = new ManagementScope(@"\\.\root\cimv2");
scope.Connect();
var searcher = new ManagementObjectSearcher(scope, new SelectQuery("SELECT MACAddress FROM Win32_NetworkAdapter WHERE PNPDeviceID='" + escapedPnpDeviceId + "'"));
foreach (ManagementObject managementObject in searcher.Get())
{
string macAddress = managementObject["MACAddress"] as string;
if (string.IsNullOrEmpty(macAddress))
throw new InvalidOperationException("No MACAddress for WMI instance Win32_NetworkAdapter.PNPDeviceID: " + pnpDeviceId);
return new MacAddress(macAddress);
}
byte[] addressBytes = networkInterface.GetPhysicalAddress().GetAddressBytes(); throw new InvalidOperationException("No MACAddress for WMI instance Win32_NetworkAdapter.PNPDeviceID: " + pnpDeviceId);
return new MacAddress(addressBytes.ReadUInt48(0, Endianity.Big));
} }
} }
} }
\ No newline at end of file
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq"> <Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
......
...@@ -45,5 +45,15 @@ namespace PcapDotNet.Core.Test ...@@ -45,5 +45,15 @@ namespace PcapDotNet.Core.Test
Assert.IsNotNull(LivePacketDeviceExtensions.GetNetworkInterface(null)); Assert.IsNotNull(LivePacketDeviceExtensions.GetNetworkInterface(null));
Assert.Fail(); Assert.Fail();
} }
[TestMethod]
public void GetMacAddressTest()
{
foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine)
{
Assert.IsNotNull(device.GetMacAddress());
Console.WriteLine(device.GetMacAddress());
}
}
} }
} }
\ No newline at end of file
...@@ -127,8 +127,8 @@ namespace PcapDotNet.Core.Test ...@@ -127,8 +127,8 @@ namespace PcapDotNet.Core.Test
} }
TimeSpan actualDiff = packet.Timestamp - lastTimestamp; TimeSpan actualDiff = packet.Timestamp - lastTimestamp;
MoreAssert.IsInRange( MoreAssert.IsInRange(
expectedDiff.Subtract(TimeSpan.FromSeconds(0.03)), expectedDiff.Subtract(TimeSpan.FromSeconds(0.06)),
expectedDiff.Add(TimeSpan.FromSeconds(0.03)), expectedDiff.Add(TimeSpan.FromSeconds(0.06)),
actualDiff); actualDiff);
} }
lastTimestamp = packet.Timestamp; lastTimestamp = packet.Timestamp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment