【发布时间】:2021-03-20 12:52:36
【问题描述】:
我有以下过程来计算tcp校验和
static inline uint32_t
csum_part(const void *buf, size_t len, uint32_t sum)
{
uintptr_t p = (uintptr_t)buf;
while (len > 1)
{
sum += *(uint16_t *)p;
len -= 2;
p += 2;
}
if (len)
sum += *(uint8_t *)p;
return sum;
}
以及下面的函数来打包它
uint16_t calc(uint32_t x)
{
while((x >> 16) != 0)
x = (x & 0xffff) + (x>>16);
return ~x;
}
当我计算标头的校验和时,我使用以下代码
uint32_t calc_tcp_checksum(char * pkt, int hdrlen, int pktlen) {
struct ip * ih = (struct ip *)
(pkt+ hdrlen - sizeof(struct tcphdr) - sizeof(struct ip));
struct tcphdr * th = (struct tcphdr *)
(pkt + hdrlen - sizeof(struct tcphdr));
#ifndef __FAVOR_BSD
th->check = 0;
#else
th->th_sum = 0;
#endif
//th->
uint32_t header_chksum = csum_part(th, sizeof(struct tcphdr), 0);
uint32_t pseudo = (uint32_t)ih->ip_src.s_addr + ih->ip_dst.s_addr +
htons(IPPROTO_TCP) + htons(pktlen);
header_chksum += pseudo;
return header_chksum;
}
我有一个如下的数据包
0000 58 f3 9c 81 2b bc 00 1c 73 13 1f 94 08 00 45 00
0010 00 dc 00 00 40 00 40 06 40 19 0a e6 35 90 ac 13
0020 0d 7a b9 be 2a 44 63 36 c2 98 c7 82 d0 1e 50 18
0030 10 00 eb 15 00 00 00 b4 00 00 09 cd 1c fb 66 40
0040 ec c7 0d 30 cb 0b e4 cb 88 74 13 3d 4e 20 00 00
0050 9a d6 00 00 00 00 9f db 4f 50 54 49 44 58 42 41
0060 4e 4b 4e 49 46 54 59 20 4d 03 8a e8 00 2d ed d0
0070 43 45 46 4e 45 30 30 30 37 20 20 20 00 01 00 02
0080 00 00 00 00 00 00 00 4b 00 00 a7 7b 00 00 00 00
0090 02 00 00 02 00 00 9a d6 39 30 30 35 39 4f 49 43
00a0 49 43 49 30 30 30 30 35 32 30 00 01 02 00 b0 6d
00b0 c8 04 42 f6 bd f9 52 7c 42 80 41 41 45 43 45 32
00c0 34 31 33 51 00 00 a1 e4 00 00 00 00 00 00 00 00
00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00e0 00 00 00 00 00 00 00 00 00 00 72 dd 89 69
在上面的例子中, pktlen = 180 hdrlen = 54
我得到校验和是 0xeb15,wireshark 说它是 0xea15。我究竟做错了什么?请注意,它总是不正确,只是有时。
【问题讨论】:
标签: networking tcp wireshark