C编程中的TCP校验和

8

我最近几天一直在尝试计算TCP的校验和,但是一直遇到困难。我在互联网上查看了很多资料,但是没有一个例子能够教你如何计算TCP的校验和。我还查看了RFC文档,但仍然无法解决:

下面是我用来生成校验和的代码:

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;
}

这个函数适用于IP校验和。

下面是我为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;
};

我一直在使用Wireshark测试这些数据包,唯一的问题是校验和错误。
最后,这里是伪头结构体,我将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;
};

一旦我使用正确的信息加载了这个结构体,然后在整个伪头结构体上使用校验和函数,并将TCP校验和赋值给该值。您是否看到我提供的任何问题?如果问题不在这里,那么可能是我看不到的粗心错误。


你如何将信息加载到结构中,它来自哪里? - Seth Noble
你还应该查看 RFC 1071,它提供了正确的 C 代码用于计算。 - user207421
4个回答


3

链接已过时。 - Perennial
@Perennial,网站已恢复并更新了链接,请查看更新 - david-hoze

3

我看到了一些问题:

  • 您没有通过填充零来考虑奇数长度的数据。
  • 读取数据包中每个字时需要考虑网络字节序。
  • 您使用 htonl(0x0000ffff) 似乎有些可疑。为什么要将常量转换为网络字节顺序,与主机字节顺序的数据结合在一起?

3

RFC 793规定:“如果一个数据段中包含奇数个需要进行校验和的头部和文本八位字节,则在校验和目的上,最后一个八位字节右侧填充零以形成一个16位字。”您上面的代码没有处理这种情况。我认为循环条件应该是i > 1,然后在循环外检查i == 1并对最后一个八位字节进行特殊处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接