【问题标题】:C Programming TCP ChecksumC 编程 TCP 校验和
【发布时间】:2012-02-09 08:06:56
【问题描述】:

我已经有好几天在为 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 校验和分配给那个值。你觉得我提供的有什么问题吗?如果问题不在这里,那可能是我看不到的粗心错误。

【问题讨论】:

  • 你如何将信息加载到结构中,它来自哪里?

标签: c tcp checksum raw-sockets


【解决方案1】:

我在 winpcap-users mailing list 上找到了一个相当不错的示例,它应该解决 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);
}

【讨论】:

    【解决方案2】:

    我看到了几件事:

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

    【讨论】:

      【解决方案3】:

      我也很难找到计算它的 c++/c 代码,直到我找到了 How to Calculate IP/TCP/UDP Checksum–Part 2 Implementation – roman10,它成功了!通过 Wireshark 的验证对其进行了测试。

      更新

      链接同时中断,将其恢复并作为要点放在我的帐户中 - How to Calculate IP/TCP/UDP Checksum

      【讨论】:

      • 链接已过时。
      • @Perennial,已恢复的站点和更新的链接,请参阅 UPDATE
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-11
        相关资源
        最近更新 更多