Get IP address of a LibPcapLiveDevice

741 views Asked by At

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: screenshot

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.

1

There are 1 answers

6
AudioBubble On BEST ANSWER

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.