[英]C Programming TCP Checksum
I have been having trouble doing the checksum for TCP for several days now.几天来,我一直在为 TCP 进行校验和处理时遇到问题。 I have looked at many sources on the Internet but none of the examples that I have seen show you how to do the TCP checksum.
我查看了 Internet 上的许多资源,但我所看到的示例都没有向您展示如何进行 TCP 校验和。 I have also looked at the RFC document and still I am having trouble:
我还查看了RFC文档,但仍然遇到问题:
Below is the code I am using to generate the checksum:下面是我用来生成校验和的代码:
unsigned short checksum(unsigned short * buffer, int bytes)
{
unsigned long sum = 0;
unsigned short answer = 0;
int i = bytes;
while(i>0)
{
sum+=*buffer;
buffer+=1;
i-=2;
}
sum = (sum >> 16) + (sum & htonl(0x0000ffff));
sum += (sum >> 16);
return ~sum;
}
This function works for the IP checksum.此功能适用于 IP 校验和。
Below is the struct I have made for my TCP header:下面是我为我的 TCP 标头制作的结构:
struct tcp_header
{
unsigned short tcp_sprt;
unsigned short tcp_dprt;
unsigned int tcp_seq;
unsigned int tcp_ack;
unsigned char tcp_res:4;
unsigned char tcp_off:4;
unsigned char tcp_flags;
unsigned short tcp_win;
unsigned short tcp_csum;
unsigned short tcp_urp;
};
I have been using Wireshark to test these packets and the only thing wrong is the checksum.我一直在使用 Wireshark 来测试这些数据包,唯一错误的是校验和。
Finally here is the pseudo header struct that I load up with the TCP header and information from the IP header:最后,这是我用 TCP 标头和来自 IP 标头的信息加载的伪标头结构:
struct pseudoTcpHeader
{
unsigned int ip_src;
unsigned int ip_dst;
unsigned char zero;//always zero
unsigned char protocol;// = 6;//for tcp
unsigned short tcp_len;
struct tcp_header tcph;
};
Once I load up this struct with the correct information I then use the checksum function on the entire pseudo header struct and assign the TCP checksum to that value.一旦我用正确的信息加载了这个结构,我就会在整个伪头结构上使用校验和函数,并将 TCP 校验和分配给该值。 Do you see anything wrong with what I have provided?
你看到我提供的东西有什么问题吗? If the problem isn't here it may be a careless error that I can't see.
如果问题不在这里,那可能是我看不到的粗心错误。
I found a fairly good example on the winpcap-users mailing list which should address Greg's comment about odd length data and give you something to compare your code against.我在winpcap-users 邮件列表上找到了一个相当不错的例子,它应该解决 Greg 关于奇数长度数据的评论,并为您提供一些比较您的代码的内容。
USHORT CheckSum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
cksum += *(UCHAR*)buffer;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
I too struggled to find c++/c code that computes it, until I found How to Calculate IP/TCP/UDP Checksum–Part 2 Implementation – roman10 , and it worked!我也很难找到计算它的 c++/c 代码,直到我找到了如何计算 IP/TCP/UDP 校验和 – 第 2 部分实现 – roman10 ,并且它奏效了! Tested it with Wireshark's validation.
使用 Wireshark 的验证对其进行了测试。
UPDATE更新
Link broke meanwhile, recovered it and put it as a gist in my account - How to Calculate IP/TCP/UDP Checksum链接同时中断,将其恢复并将其作为要点放入我的帐户 - 如何计算 IP/TCP/UDP 校验和
I see a couple of things:我看到了几件事:
htonl(0x0000ffff)
seems suspicious.htonl(0x0000ffff)
似乎很可疑。 Why are you converting a constant to network byte order to combine it with data in host byte order?RFC 793 says "If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes." RFC 793说“如果一个段包含奇数个要校验和的报头和文本八位字节,最后一个八位字节在右边用零填充,以形成一个 16 位字,用于校验和目的。” Your code above does not handle that case.
您上面的代码不处理这种情况。 I think the loop conditional should be i > 1 and then check for i == 1 outside the loop and do the special handling for the last octet.
我认为循环条件应该是 i > 1 然后在循环外检查 i == 1 并对最后一个八位字节进行特殊处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.