Mac更改IP总长度字段

时间:2012-12-11 22:39:57

标签: macos sockets ip wireshark

我在Mac 10.6.8中使用套接字进行编程。每当我收到一个数据包时,它都会从IP头开始。我一直在使用Wireshark来分析传入的数据包,我注意到我的机器的套接字实现将持续改变"总长度" IP标头中的字段。具体来说,它将减去IP头长度并反转字节(从网络到主机顺序)。

例如,这是Wireshark报告的IP头的开头:

45 c0 00 38 ...

分解如下:

  • 4位(0x4):IP版本:4
  • 4位(0x5):IP头长度:5个字(20个字节)
  • 8位(0xc0):差异化服务标志
  • 16位(0x0038):总长度:56字节

但是,当我为同一个数据包打印由recvfrom填充的缓冲区的内容时,我会得到一个不同的文字:

ssize_t recvbytes = recvfrom(sock->fd, buffer, size, /*flags=*/0,
  (struct sockaddr*)src, &src_len);

返回

45 c0 24 00 ...
  • 4位(0x4):IP版本:4
  • 4位(0x5):IP头长度:5个字(20个字节)
  • 8位(0xc0):差异化服务标志
  • 16位(0x2400):总长度:9216字节(?!)

我发现在我访问缓冲区之前,套接字实现正在读取总长度,减去IP头长度,然后按主机顺序(我的机器上的小端)而不是网络顺序写回(大端)。在这个例子中,这意味着:

  • 读取总长度:0x0038 = 56
  • 减去标题长度:56 - 20 = 36
  • 以主机顺序回写:36 = 0x0024(big endian)= 0x2400(little endian =我机器上的主机顺序)

问题变得更糟。它不会只是改变最外层IP头的总长度。它还将改变内部IP报头的总长度字段,例如,埋在ICMP中的那个字段"时间超过" message(必须包含丢弃数据包的原始IP头)。有趣的是,它不会从内部标题中减去IP标题长度;它只是反转字节顺序。

这是否发生在其他人身上?它是我不知道的标准的一部分吗?有没有办法修复我的机器的套接字实现以停止篡改数据包? Wireshark如何解决这个问题?

提前感谢您的考虑。

编辑:我的代码和Makefile可用on GitHub。我写了一个fixip_osx函数来验证IP校验和:

https://github.com/thejohnfreeman/netutils/blob/master/lib/ip.c

void fixip_osx(struct ip* ip) {
  /* Something on my Mac subtracts the header length from `ip_len` and stores
   * it in host order (little endian). */
  u16_t ip_hdrlen = ip->ip_hl << 2;
  u16_t ip_totlen = ip->ip_len + ip_hdrlen;
  ip->ip_len = htons(ip_totlen);
}

但是,当有效负载包含另一个IP头时,验证ICMP校验和仍然是一个问题。

无论是使用Clang 3.2(从trunk构建)还是GCC 4.7(MacPorts端口)编译都存在问题,因此我认为问题在于套接字实现(与Mac OS一起打包)或Mac OS X本身。 / p>

2 个答案:

答案 0 :(得分:2)

BSD平台套件(不包括OpenBSD)以主机字节顺序显示IP偏移量和长度。所有其他平台以接收的网络字节顺序出现。这是一个“功能”,在IP(4) - Internet Protocol(FreeBSD,OS X)的手册页中引用。

  

必须以主机字节顺序提供ip_len和ip_off字段。   必须以网络字节顺序提供所有其他字段。

在FreeBSD / NetBSD中,IP长度可以等于packet length - IP header length

参考: Stevens / Fenner / Rudolph,Unix网络编程第1卷,第739页

我必须使用PGM网络协议的用户空间实现处理这些异常,具体代码:

https://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/packet_parse.c#76

检测AutoConf实际上非常烦人,我认为所有软件包都是基于每个平台进行硬编码的。我已经看到本周在这个问题上提出的错误报告(header byte order config options detected incorrectly)。

答案 1 :(得分:0)

Mac本身不太可能这样做。如果是这样的话,那将从根本上打破IP协议。更有可能的是捕获数据包并将它们传递给recvfrom()(可能是你正在进行混杂的网络捕获,对吗?)是在Mac完成处理之后转换数据的原因。 ireshark在较低级别运行,可以访问实际的网络数据。