IPv6 라우터 알림 패킷을받는 Linux 사용자 공간 프로그램에서 작업하고 있습니다. RFC4861의 일환으로 ICMPv6 체크섬을 확인해야합니다. 내 연구를 기반으로, IPv6 의사 헤더와 패킷 내용의 칭찬 체크섬을 계산하면 일반적으로 IP 체크섬을 참조하는 것이 가장 일반적입니다. 결과는 0xffff 여야합니다. 하지만 0x3fff의 체크섬을 계속 가져옵니다.ICMPv6 체크섬의 유효성을 검사하려면 어떻게합니까? (왜 0x3fff의 체크섬을 계속 사용합니까?)
체크섬 구현에 문제가 있습니까? 리눅스 커널은 패킷을 사용자 공간에 전달하기 전에 ICMPv6 체크섬을 확인합니까? 거기에 좋은 ICMPv6 패킷 테스트를위한 좋은 레퍼런스 소스가 무엇입니까?
uint16_t
checksum(const struct in6_addr *src, const struct in6_addr *dst, const void *data, size_t len) {
uint32_t checksum = 0;
union {
uint32_t dword;
uint16_t word[2];
uint8_t byte[4];
} temp;
// IPv6 Pseudo header source address, destination address, length, zeros, next header
checksum += src->s6_addr16[0];
checksum += src->s6_addr16[1];
checksum += src->s6_addr16[2];
checksum += src->s6_addr16[3];
checksum += src->s6_addr16[4];
checksum += src->s6_addr16[5];
checksum += src->s6_addr16[6];
checksum += src->s6_addr16[7];
checksum += dst->s6_addr16[0];
checksum += dst->s6_addr16[1];
checksum += dst->s6_addr16[2];
checksum += dst->s6_addr16[3];
checksum += dst->s6_addr16[4];
checksum += dst->s6_addr16[5];
checksum += dst->s6_addr16[6];
checksum += dst->s6_addr16[7];
temp.dword = htonl(len);
checksum += temp.word[0];
checksum += temp.word[1];
temp.byte[0] = 0;
temp.byte[1] = 0;
temp.byte[2] = 0;
temp.byte[3] = 58; // ICMPv6
checksum += temp.word[0];
checksum += temp.word[1];
while (len > 1) {
checksum += *((const uint16_t *)data);
data = (const uint16_t *)data + 1;
len -= 2;
}
if (len > 0)
checksum += *((const uint8_t *)data);
printf("Checksum %x\n", checksum);
while (checksum >> 16 != 0)
checksum = (checksum & 0xffff) + (checksum >> 16);
checksum = ~checksum;
return (uint16_t)checksum;
}
큰 또는 작은 엔디안 컴퓨터에서 실행되고 있습니까? – Alnitak
리틀 엔디안 (x86_64)이지만 내가 체크섬을 확인한 내용은 엔디안과 독립적이어야합니다. – dlundquist
+1 "내 연구를 기반으로" – Flexo