C 编程 TCP 校验和

发布于 2024-12-26 07:00:44 字数 1372 浏览 1 评论 0原文

几天来我在执行 TCP 校验和时遇到了麻烦。我查看了 Internet 上的许多资源,但我看到的示例都没有向您展示如何进行 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 校验和分配给那个值。您认为我提供的内容有什么问题吗?如果问题不在这里,那可能是我看不到的粗心错误。

I have been having trouble doing the checksum for TCP for several days now. 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. I have also looked at the RFC document and still I am having trouble:

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.

Below is the struct I have made for my TCP header:

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.

Finally here is the pseudo header struct that I load up with the TCP header and information from the IP header:

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. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

哭了丶谁疼 2025-01-02 07:00:44

我在 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 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.

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);
}
九命猫 2025-01-02 07:00:44

RFC 793 表示“如果一个段包含奇数个要校验和的标头和文本八位字节,最后一个八位字节在右侧填充零,形成 16 位字,用于校验和。”您上面的代码不能处理这种情况。我认为循环条件应该是 i > 1 然后在循环外检查 i == 1 并对最后一个八位字节进行特殊处理。

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." 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.

北城挽邺 2025-01-02 07:00:44

我也很难找到计算它的 c++/c 代码,直到我发现 如何计算 IP/TCP/UDP 校验和 – 第 2 部分实现 – roman10,它成功了!用Wireshark的验证进行了测试。

更新

链接同时损坏,恢复它并将其作为要点放入我的帐户中 -
如何计算 IP/TCP/UDP 校验和

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! Tested it with Wireshark's validation.

UPDATE

Link broke meanwhile, recovered it and put it as a gist in my account -
How to Calculate IP/TCP/UDP Checksum

半﹌身腐败 2025-01-02 07:00:44

我看到了一些事情:

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

I see a couple of things:

  • You are not accounting for odd length data by padding with zero.
  • You will need to account for network byte order when reading each word from the packet.
  • Your use of htonl(0x0000ffff) seems suspicious. Why are you converting a constant to network byte order to combine it with data in host byte order?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文