计算ICMPv6数据包的校验和

时间:2013-03-30 12:36:12

标签: c# checksum icmp

我正在尝试在 C#中计算ICMPv6数据包的校验和。我按照here发布的建议,但似乎仍然存在细微差别。

这就是我计算校验和的方法:

        //Note: Initial checksum in payload is set to 0x00, 0x00
        //Add ip source bytes (16 bytes)
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 0);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 2);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 4);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 6);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 8);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 10);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 12);
        checksum += Utilities.BitConverterToUInt16(IpV6SourceBytes, 14);

        //Add ip destination bytes (16 bytes)
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 0);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 2);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 4);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 6);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 8);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 10);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 12);
        checksum += Utilities.BitConverterToUInt16(IpV6DestinationBytes, 14);

        //Add length (2 bytes) - tested, value is correct (32 for {0x00, 0x20})
        checksum += Utilities.BitConverterToUInt16(ip6.PayloadLength, 0);

        //Add next-header (1 byte) - tested, value is correct (58)
        checksum += (byte)ip6.NextProtocol;

        //Add ICMPv6 message
        for (int i = 0; i < buffer.Length; i +=2) {
            checksum += Utilities.BitConverterToUInt16(buffer, i);
        }

        checksum += (ushort)(checksum >> 16);
        checksum = (ushort)~checksum;

        Console.WriteLine(checksum);
        Checksum = BitConverter.GetBytes((UInt16)checksum).Reverse().ToArray();

Utilities.BitConverterToUint16 方法:

    public static ushort BitConverterToUInt16(byte[] value, int startIndex) {
        return BitConverter.ToUInt16(value.Reverse().ToArray(),
          value.Length - sizeof(UInt16) - startIndex);
    }

Wireshark的意见: 校验和:0x4201 [不正确,应为0x4209]

我错过了什么?

编辑:注意: Utilities.BitConverterToUInt16检索接下来的2个字节(16位)。我引用的帖子使用4个字节(32位)作为有效载荷长度,即使该字段长度为2个字节。我不知道为什么另一篇文章使用了4个字节,这就是为什么我很困惑。

Edit2:好的,我几乎到处搜索,无法识别问题。

  • 来自wiki: 根据IPv6标准从IPv6标头字段的伪标头开始计算校验和,该标准由源和目标地址,数据包长度和下一个标头字段组成,后者设置为值58.在此伪标头之后,校验和继续使用ICMPv6消息,其中校验和最初设置为零。
  • 来自ietf 校验和是整个ICMPv6消息的一个补码和的16位补码,以ICMPv6消息类型字段开头,前缀为IPv6标头字段的“伪标头”
  • 来自this问题: “......这是不必要的.len总是16位。” “......常数总是00 00 00 58,所以只需添加58。”

这让我很生气。如果有人能指出我正确的方向,我会非常感激。我绝对不知道为什么校验和错了。再次感谢。

编辑3:不确定这是否有用但似乎校验和总是小8(即使我更改了IPv6标头中的所有值,例如IP地址)。

0 个答案:

没有答案