我正在尝试计算 ICMPv6 消息的校验和(准确地说,是邻居广告)。
RFC 4443将其描述为“整个 ICMPv6 消息的反码和的 16 位反码”
还有一些关于如何做到这一点的示例代码(虽然我认为它来自 IPv4,但唯一的区别是总和中包含的内容,而不是如何计算它): RFC 1071
我从 Wireshark 拿了一个数据包,并按主机字节顺序输入了短裤。然后我打印正确的校验和,将其归零并计算我的。但它们不匹配。根据 RFC 1071,字节序不应该是问题(结果不仅仅是字节交换,而是完全关闭)。
根据RFC 2460 #8.1,我需要在计算中包含“伪标头”,仅包含 Src+Dst 地址、长度为 32 位宽字段和下一个标头类型。
调用代码:
uint32_t payloadlen = htonl(32);
struct ip6_hdr *ip6;
struct nd_neighbor_advert *na;
size_t len, offset, tmplen;
uint8_t *tmppacket, icmp = 58;
uint8_t packet[] = {
0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3A, 0xFF, 0x20, 0x01, 0x0D, 0xB8,
0xDD, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x54, 0xFF,
0xFE, 0x00, 0x22, 0x00, 0x88, 0x00, 0x54, 0xB9, 0x60, 0x00, 0x00, 0x00,
0x20, 0x01, 0x0D, 0xB8, 0xDD, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x02, 0x01, 0x00, 0x03, 0x54, 0x00, 0x00, 0x13
};
na->nd_na_hdr.icmp6_cksum = 0;
tmplen = 40+sizeof(struct nd_neighbor_advert)+ICMP_OPT_LEN;
tmppacket = malloc(tmplen);
memset(tmppacket, 0, 40);
offset = sizeof(struct in6_addr);
memcpy(tmppacket, &ip6->ip6_src, offset);
memcpy(tmppacket+offset, &ip6->ip6_dst, offset);
memcpy(tmppacket+offset*2, &payloadlen, 4);
memcpy(tmppacket+39, &icmp, 1);
memcpy(tmppacket+40, packet+sizeof(struct ip6_hdr),
sizeof(struct nd_neighbor_advert)+ICMP_OPT_LEN);
na = (struct nd_neighbor_advert *) (tmppacket+40);
na->nd_na_hdr.icmp6_cksum = checksum((uint16_t *) tmppacket, tmplen);
printf("Checksum calc: %hX\n", na->nd_na_hdr.icmp6_cksum);
dump((unsigned char *) tmppacket, tmplen);
校验和函数:
uint16_t checksum (uint16_t *addr, size_t bytes) {
unsigned int i;
uint16_t *p = addr;
uint32_t sum = 0;
/* Sum */
for (i=bytes; i > 1; i -= 2)
sum += *p++;
/* If uneven length */
if (i > 0)
sum += (uint16_t) *((unsigned char *) (p));
/* Carry */
while ((sum & 0xFFFF0000) != 0)
sum = (sum >> 16) + (sum & 0xFFFF);
return ~((uint16_t) sum);
}
这只是快速和肮脏的让它开始工作。“main”的代码省略了一些东西。校验和函数中的字节序应该不是问题,而且这个数据包的长度是偶数。
结果应该是 B954,但我得到的是 DB32。转储的输出是:
包
大小
感谢到目前为止的提示。如果您知道还有什么问题,我会很感激您的意见。