【问题标题】:Calculating the checksum of an IPv4 packet计算 IPv4 数据包的校验和
【发布时间】:2017-03-21 11:58:15
【问题描述】:

如何计算收到的示例 IPv4 数据包的校验和,如下所示:

4500 062A 42A1 8001 4210 XXXX C0A8 0001 C0A8 0003

其中xxxx 是需要与数据包一起发送的校验和。

到目前为止,这是我发现的: 转换为二进制,加,然后是和的补码,一旦转换回来应该是校验和?但我无法做到这一点:

4500 062A 42A1 8001 4210 XXXX C0A8 0001 C0A8 0003

4500 - 0100 0101 0000 0000

062A - 0000 0110 0010 1010

42A1 - 0100 0010 1010 0001

8001 - 1000 0000 0000 0001

xxxx - 0000

C0A8 - 1100 0000 1010 1000

0003 - 0000 0000 0000 0011

全部添加:

4500 - 0100 0101 0000 0000 062A - 0000 0110 0010 1010


19242 - 0100101100101010 //第一个结果 42A1 - 0100 0010 1010 0001


36299 - 01000110111001011 //第二个结果 8001 - 1000 0000 0000 0001


69068 - 010000110111001100 //第三个结果 C0A8 - 1100 0000 1010 1000


118388 - 011100111001110100 0003 - 0000 0000 0000 0011

118391 - 011100111001110111 取118391-100011000110001000的补码

—> 23188 - 100011000110001000

校验和也是 23188 吗??

【问题讨论】:

  • 我可以看到你在这个问题上付出了一些努力。如果你敢再问一个关于 SO 的问题,bengalurean,有一些方法可以改进它。首先,尽量让你的问题简单。清楚地陈述你的问题,说出你期望得到什么,以及你得到了什么。有时您需要添加详细的示例和代码,但除非必须,否则不要这样做。如果这样做,请使用格式将其放入代码块中,以便于阅读。我希望你能够坚持解决这个问题。阅读一个人的补语,直到你彻底理解为止。
  • 另外,在标题中使用标准英文。你做得很好,除了你的标题。 “计算校验和 ipv4 数据包”可以改进为“计算 IPv4 数据包的校验和”或“如何计算 IPv4 校验和以验证收到的数据包?”

标签: networking ip ipv4


【解决方案1】:

RFC 791, INTERNET PROTOCOL 中描述了 IPv4 标头校验和:

标头校验和:16 位

仅在标头上的校验和。由于某些标头字段发生了变化(例如, 生存时间),这将在每个点重新计算和验证 互联网标头已处理。

校验和算法为:

校验和字段是一个的 16 位反码 报头中所有 16 位字的补码总和。出于以下目的 计算校验和,校验和字段的值为零。

这是一个简单的计算校验和和实验证据 表示它是足够的,但它是临时的,可以替换为 CRC 程序,取决于进一步的经验。

此算法在RFC 1071, Computing the Internet Checksum 中有详细说明,由RFC 1141, Incremental Updating of the Internet Checksum 更新,由RFC 1624, Computation of the Internet Checksum via Incremental Update 更新。

【讨论】:

  • 是的,我在其他帖子中看到了这篇文章,但不幸的是没有帮助。
  • 即使有代码示例,您也无法理解 RFC 中的详细算法?
  • 不,我没有。 :(
  • 我不知道该告诉你什么。 RFC 1071 为您提供了一个简单的 C 示例来说明如何做到这一点。您应该能够将其翻译成几乎任何语言。
  • @labyrinth "可能不知道一点 C (或任何其他语言)" 我认为一个人会/不应该问关于编程的问题如果该人不知道如何编程,则该站点(还有其他用于网络理论的 SE 站点)。它真的没有比拥有一个如何做你想做的事情的代码示例更简单的了。事实上,没有其他人,包括你,甚至试图回答这个问题。你的答案在哪里?你会为他写更简单的代码吗?
【解决方案2】:

关于 IPv4 校验和计算,有四个 RFC 可供阅读:

RFC 791、RFC 1071、RFC 1141 和 RFC 1624。

我没有阅读它们,直到我遇到一个非常奇怪的问题,我不打算这样做。但是还有另一个很棒的页面谈论 IPv4 的校验和字段:Wikipedia's IPv4 Header Checksum。按照 Wikipedia 上的示例,我尝试计算校验和:

步骤 1. 计算所有 IPv4 标头字段的反码和

我们可以将所有这些数字以十六进制或二进制形式相加。这两种方法我都会做:

步骤 1a.1:我将添加前两个字段 (4500 + 062A)。然后,我将第三个字段添加到先前添加的结果 (4B2A+42A1)。从那里开始,我会将下一个字段的值添加到累计总和中。

              1             1111            1       1
4500    4B2A   8DCB  10DCC  14FDC  21084  21085  2D12D
062A    42A1   8001   4210   C0A8   0001   C0A8   0003
-----  -----   ----  -----  -----  -----  -----  -----
4B2A    8DCB  10DCC  14FDC  21084  21085  2D12D  2D130

步骤 1b.1

In octave:
-------------------

octave:14> hex2dec("4500")+hex2dec("062a")+hex2dec("42a1")+hex2dec("8001")+hex2dec("4210")+hex2dec("c0a8")+hex2dec("0001")+hex2dec("c0a8")+hex2dec("0003")
ans =  184624
octave:15> 
octave:15> dec2hex(184624)
ans = 2D130
octave:16>

步骤 1a.2:步骤 1a.1 的加法是一组数字的简单数学加法。另一方面,在补码加法中,我们还需要做一件事。由于结果必须适合 16 位(意味着结果应该是 4 个十六进制数字),因此这意味着我们必须处理结果的最高有效位。 0x2D130 中的“2”必须在某个地方,因为补码加法必须与我们添加的所有数字具有相同的长度。在一个补码加法中,我们将溢出的数字加回数字中。所以,0xD130+ 0x2 = 0xD132

然后标题字段的补码是:0xD132

步骤 1b.2:

In octave:
-------------------

octave:14> hex2dec("4500")+hex2dec("062a")+hex2dec("42a1")+hex2dec("8001")+hex2dec("4210")+hex2dec("c0a8")+hex2dec("0001")+hex2dec("c0a8")+hex2dec("0003")
ans =  184624
octave:15> dec2hex(184624)
ans = 2D130
octave:16> 16^4
ans =  65536
octave:17> 184624-(2*65536)
ans =  53552
octave:18> 184624-(2*65536)+2
ans =  53554
octave:19> dec2hex(184624-(2*65536)+2)
ans = D132
octave:20> 

步骤 1c.1:

将字段转换为二进制:

4500: 0100 0101 0000 0000
062A: 0000 0110 0010 1010 
42A1: 0100 0010 1010 0001
8001: 1000 0000 0000 0001
4210: 0100 0010 0001 0000
C0A8: 1100 0000 1010 1000
0001: 0000 0000 0000 0001
C0A8: 1100 0000 1010 1000
0003: 0000 0000 0000 0011

4500+062A:
00 0100 0101 0000 0000+
00 0000 0110 0010 1010
-----------------------
00 0100 1011 0010 1010 (04B2A)

+42A1
00 0100 1011 0010 1010+
00 0100 0010 1010 0001
-----------------------
00 1000 1101 1100 1011 (08DCB)    

+8001

00 1000 1101 1100 1011+
00 1000 0000 0000 0001
------------------------
01 0000 1101 1100 1100 (10DCC)

+4210
01 0000 1101 1100 1100+
00 0100 0010 0001 0000
------------------------
01 0100 1111 1101 1100 (14FDC)

+C0A8
01 0100 1111 1101 1100+
00 1100 0000 1010 1000
-----------------------
10 0001 0000 1000 0100 (21084)

+0001
10 0001 0000 1000 0100+
00 0000 0000 0000 0001
-----------------------
10 0001 0000 1000 0101 (21085)

+C0A8
10 0001 0000 1000 0101+
00 1100 0000 1010 1000
-----------------------
10 1101 0001 0010 1101 (2D12D)

+0003
10 1101 0001 0010 1101+
00 0000 0000 0000 0011
-----------------------
10 1101 0001 0011 0000 (2D130)

步骤 1c.2: 将数字加 10(最左边的位):

1101 0001 0011 0000+
0000 0000 0000 0010
--------------------
1101 0001 0011 0010 (D132)

第 2 步。

无论您如何进行反码加法,您现在都必须取结果的反码。任何二进制数的补码只是“翻转数字中的所有位”的花哨名称:

1101 0001 0011 0010 -> 0010 1110 1100 1101 (2ECD)

如果你想取一个十六进制数字的补码而不转换为二进制,下面是一个方便的表格:

n 1'
0 F
1 E
2 D
3 C
4 B
5 A
6 9
7 8
8 7
9 6
A 5
B 4
C 3
D 2
E 1
F 0

所以取 D132 的补码为:

D->2
1->E
3->C
2->D

所以 IPv4 标头 4500 062A 42A1 8001 4210 XXXX C0A8 0001 C0A8 0003 的校验和是 0x2ECD

一个演示步骤的小型围棋程序:

https://go.dev/play/p/DOj28mjuqtP

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 2015-08-31
    • 2013-02-02
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 2010-12-01
    相关资源
    最近更新 更多