Since the SharpPcap project claims to be compatible with Mono I decided to get my project running on a Mac.
For this I had to make the WinPcapDevice
a LibPcapLiveDevice
and map the WinPcap.dll
to the libpcap.dylib
.
SharpPcap.dll.config:
<configuration>
<dllmap dll="wpcap" target="libpcap.1.6.2.dylib" />
</configuration>
code:
private static string GetFilterString(ICaptureDevice captureDevice)
{
var device = (LibPcapLiveDevice) captureDevice;
return String.Format("((tcp dst port 80) and (src net {0})) or ((dst net {0}) and (tcp src port 80))", device.Addresses[1]);
}
Problem is, that the property device.Addresses
is empty and I can't find any other property that would contain the IP address. Actually almost all properties are empty, except for the device name and its MAC address.
I'm not sure wether this is a problem caused by SharpPcap or Libpcap.
EDIT
As Guy Harris suggested I compared the structs and types used in the PcapUnmanagedStructures.cs
with the Apple OS Reference Docs. I tried to adapt them, so they would match the OS' specification:
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr
{
public byte sa_family; /* address family */
[MarshalAs(UnmanagedType.ByValArray, SizeConst=14)]
public byte[] sa_data; /* 14 bytes of protocol address */
};
public struct in_addr
{
public UInt32 s_addr; //in_addr_t
}
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr_in
{
public byte sa_family; /* address family */
public UInt16 sa_port; /* port */
public in_addr sin_addr; /* address */
// char sin_zero[8]; not sure this whether to add this as it was contained in the doc
// pad the size of sockaddr_in out to 16 bytes
MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
// Disable warnings around this unused field
#pragma warning disable 0169
private byte[] pad; // not sure about this one either
#pragma warning restore 0169
};
[StructLayout(LayoutKind.Sequential)]
internal struct sockaddr_in6
{
public byte sin6_family; /* address family */
public UInt16 sin6_port; /* Transport layer port # */
public UInt32 sin6_flowinfo; /* IPv6 flow information */
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] // raised it to 32 as the struct in6_addr contains an element of type __uint32_t
public byte[] sin6_addr; /* IPv6 address */
public UInt32 sin6_scope_id; /* scope id (new in RFC2553) */
};
I'm not sure I did it right, since the ipAddress
is still empty:
EDIT 2
Guy Harris was right about that lenght field. This is what works for me now:
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr
{
public byte sa_len;
public byte sa_family;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=14)]
public byte[] sa_data;
};
public struct in_addr
{
public UInt32 s_addr;
}
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr_in
{
public byte sin_len;
public byte sin_family;
public UInt16 sin_port;
public in_addr sin_addr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
public byte sin_zero;
};
Note that I also changed some field's name prefix from sa
to sin
. I also changed the pad
's name to sin_zero
. Quite easy after all.
Well, I'm not familiar with C#, but, if PcapUnmanagedStructures.cs is attempting to describe the layout of the native C structures for the OS, those declarations aren't correct for many UN*Xes, including BSD-flavored UN*Xes such as OS X - those structures begin with a one-byte length field followed by a one-byte address family field, not with a two-byte address family field.
So all the
UInt16
family fields in the sockaddr structures there don't match the layout of the structures in OS X - or in {Free,Net,Open,DragonFly}BSD. They might not match in some other UN*Xes, either, even though they might match in Linux.Whether this is what's causing your problem is another matter.