1

由于 SharpPcap 项目声称与 Mono 兼容,我决定让我的项目在 Mac 上运行。

为此,我必须制作WinPcapDeviceaLibPcapLiveDevice并将其映射WinPcap.dlllibpcap.dylib.

SharpPcap.dll.config:

<configuration>
    <dllmap dll="wpcap" target="libpcap.1.6.2.dylib" />
</configuration> 

代码:

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]);
}

问题是,该属性device.Addresses是空的,我找不到任何其他包含 IP 地址的属性。实际上几乎所有属性都是空的,除了设备名称和它的 MAC 地址。我不确定这是由 SharpPcap 还是 Libpcap 引起的问题。

编辑

正如 Guy Harris 建议的那样,我将 中使用的结构和类型PcapUnmanagedStructures.cs与 Apple OS 参考文档进行了比较。我试图调整它们,以便它们符合操作系统的规范:

[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) */
};

我不确定我做对了,因为ipAddress仍然是空的: 截屏

编辑 2

盖伊哈里斯关于那个长场是正确的。这就是现在对我有用的方法:

[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;
};

请注意,我还将某些字段的名称前缀从sa更改为sin。我也将pad's name 更改为sin_zero. 毕竟很容易。

4

1 回答 1

1

好吧,我不熟悉 C#,但是,如果PcapUnmanagedStructures.cs试图描述操作系统的本机 C结构的布局,那么这些声明对于许多 UN*Xes 是不正确的,包括 BSD 风格的 UN*Xes例如 OS X - 这些结构以一字节长度字段开头,后跟一字节地址族字段,而不是两字节地址族字段。

因此UInt16,sockaddr 结构中的所有族字段都与 OS X 中的结构布局不匹配 - 或 {Free,Net,Open,DragonFly}BSD 中的结构布局。它们在其他一些 UN*X 中也可能不匹配,即使它们在 Linux 中可能匹配。

这是否是导致您的问题的原因是另一回​​事。

于 2014-12-11T22:19:06.903 回答