gpt4 book ai didi

ruby - 如何计算 RFC 791 IP header 校验和?

转载 作者:太空宇宙 更新时间:2023-11-03 16:11:50 25 4
gpt4 key购买 nike

我正在为一个自学 Ruby 项目滚动我自己的 IP 数据包,并且需要计算 IP header 校验和(如 RFC 791 p.14 中所述)。当我在这里输入我的问题时弹出的相关问题之一将我指向 RFC 1071,所以我可能大部分都在那里,但只是为了添加到 Stack Overflow,任何人(可能是 Future Josh)都可以提供一些 Ruby 代码用于计算校验和,假设使用以下 Ruby 位:

    def build_ip_packet(tos, ttl, protocol, dst_addr, data)
len = (IP_HEADER_LEN * 4) + data.size

ip_header = %w{ #{IP_VERSION} #{IP_HEADER_LEN} #{tos} #{len} #{IP_IDENTIFICATION} #{IP_FLAGS_BIT_0} #{IP_FLAGS_BIT_1} #{IP_FLAGS_BIT_2} #{IP_FRAG_OFFSET} #{ttl} #{protocol} #{hdr_checksum} #{src_addr} #{dst_addr} }

[...]
end

常量在文件顶部定义,但如果您查看 RFC791 p.11,它们应该是不言自明的。

最佳答案

RFC 1071在 C 中提供以下示例实现:

in 6
{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;

while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short) addr++;
count -= 2;
}

/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;

/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);

checksum = ~sum;

我写了下面的 C 代码来对其进行单元测试:

#include <stdio.h>
#include <stdlib.h>


unsigned short checksum (int count, unsigned short * addr) {
unsigned long sum = 0;

while (count > 1) {
sum += *addr++;
count -= 2;
}

// Add left-over byte, if any
if (count > 0)
sum += * (unsigned char *) addr;

while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);

return (unsigned short)sum;
}

void test (const unsigned short expected, const unsigned short got) {
printf(
"%s expected 0x%04x, got 0x%04x\n",
(expected == got ? "OK" : "NOK"),
expected,
got
);
}

int main(void) {
unsigned short *buf = calloc(1024, sizeof(unsigned short));

buf[0] = 0x0000;

test(
0x0,
checksum(2, buf)
);

buf[0] = 0x0001;
buf[1] = 0xf203;
buf[2] = 0xf4f5;
buf[3] = 0xf6f7;

test(
0xddf2,
checksum(8, buf)
);

return 0;
}

有点令人不安的是,我的代码没有像 RFC 实现那样在 checksum() 函数的最后一行采用 sum 的按位 NOT,但是添加按位 NOT 破坏了我的单元测试.

运行代码产生:

: jglover@jglover-3; /tmp/rfc-1071-checksum 
OK expected 0x0000, got 0x0000
OK expected 0xddf2, got 0xddf2

我将其移植到 Ruby,如下所示:

def rfc1071_checksum(header_fields)
checksum = 0

header_fields.each{|field| checksum += field}

while (checksum >> 16) != 0
checksum = (checksum & 0xffff) + (checksum >> 16)
end

return checksum
end

我这样调用方法:

def build_ip_packet(tos, ttl, protocol, dst_addr, data)
len = (IP_HEADER_LEN * 4) + data.size

# Header checksum is set to 0 for computing the checksum; see RFC 791 p.14
hdr_checksum = 0

src_addr = IPAddr.new('127.0.0.1')

header_fields = [
( ((IP_VERSION << 4) + IP_HEADER_LEN) << 8 ) + ( tos ),
len,
IP_IDENTIFICATION,
( (IP_FLAGS_BIT_0 << 15) + (IP_FLAGS_BIT_1 << 14) + (IP_FLAGS_BIT_2 << 13) + (IP_FRAG_OFFSET << 12)),
( ttl << 8 ) + ( protocol ),
hdr_checksum,
src_addr & 0xff00, # 16 most significant bits
src_addr & 0x00ff, # 16 least significant bits
dst_addr & 0xff00, # 16 most significant bits
dst_addr & 0x00ff, # 16 least significant bits
]

hdr_checksum = rfc1071_checksum(header_fields)

return nil
end

下面是单元测试:

require 'test/unit'
require 'lib/traceroute'

class TestTraceroute < MiniTest::Unit::TestCase
def test_rfc1071_checksum
[
[ 0x0000, [ 0x0000 ] ],
[
0xddf2,
[
0x0001f203,
0xf4f5f6f7,
]
],
].each{|input_record|
got = Traceroute.new.rfc1071_checksum(input_record[1])
expected = input_record[0]

assert_equal(got, expected, "rfc1071_checksum: #{input_record[1].inspect}")
}
end
end

关于ruby - 如何计算 RFC 791 IP header 校验和?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1962746/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com