You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C语言计算IP校验和遇问题:对照RFC1071代码仍无效

排查IP校验和计算代码的问题

我帮你梳理几个关键问题,这些都是导致代码无法正常工作的核心原因:

1. 未清零校验和字段(最致命的错误)

RFC 1071明确要求,计算IP首部校验和时,必须先将首部的chksum字段设置为0。因为校验和是对除自身外所有首部字段的16位字求和后取反得到的。你的代码完全跳过了这一步,计算时会包含原来的校验和值,直接导致结果彻底错误。

2. 结构体字节对齐隐患

虽然你的IP结构体看起来总长度是20字节,但C编译器默认的对齐规则可能会在字段之间插入填充字节(比如为了对齐uint32_t类型),导致结构体实际大小大于20字节。此时你的代码遍历整个结构体时,会把这些无效的填充数据加入求和,破坏校验和计算。

3. 奇数字节处理不符合RFC要求

当首部长度为奇数时(虽然20字节是偶数,但代码逻辑需要严谨),RFC要求将最后一个字节作为16位字的高字节(低字节补0)加入总和。你的代码直接将其作为低字节加入(sum += *(uint8_t*)buf),这会导致数值计算错误。

4. 字节序不匹配问题

IP首部的所有字段都采用网络字节序(大端),如果你的结构体中存储的是主机字节序(比如小端机器上的本地字节序),直接将结构体转换为uint16_t*遍历计算时,每个16位字的字节顺序会颠倒,导致求和结果错误。


修正后的代码示例

首先修正IP结构体(解决对齐问题)

使用编译指令强制1字节对齐,同时修正字段命名更符合IP首部定义:

// 强制1字节对齐,避免填充字节(GCC/Clang可用__attribute__((packed)),MSVC用#pragma pack)
#pragma pack(push, 1)
typedef struct ip_h {
    uint8_t ver_ihl;    // 高4位=版本,低4位=IHL(首部长度)
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    uint16_t frag_off;
    uint8_t ttl;
    uint8_t proto;
    uint16_t chksum;
    uint32_t src;
    uint32_t dst;
} IP;
#pragma pack(pop)

修正后的校验和计算函数

uint16_t calculate_ip_chksum(IP *ip) {
    uint16_t *buf = (uint16_t *)ip;
    uint32_t sum = 0;
    // 从ver_ihl字段提取IHL(低4位),计算首部总字节数
    int counter = (ip->ver_ihl & 0x0F) * 4;

    // 关键步骤:先清零校验和字段
    ip->chksum = 0;

    // 遍历所有16位字求和
    while (counter > 1) {
        // 如果结构体存储的是主机字节序,需要先转网络字节序再相加
        // 如果是直接从网络数据包映射的结构体,直接用*buf即可
        sum += ntohs(*buf++);
        counter -= 2;
    }

    // 处理奇数字节(符合RFC要求:作为高字节,补0低字节)
    if (counter == 1) {
        sum += (*(uint8_t *)buf) << 8;
    }

    // 折叠32位总和的高位到低16位
    while (sum >> 16) {
        sum = (sum & 0xFFFF) + (sum >> 16);
    }

    // 取反后转网络字节序返回(IP首部校验和是网络字节序)
    uint16_t checksum = ~sum;
    return htons(checksum);
}

额外注意事项

  • 如果是构造IP首部,所有多字节字段(如tot_len、id、src、dst)都需要用htons()/htonl()转换为网络字节序后再存入结构体。
  • 如果是解析收到的数据包,直接将网络缓冲区映射到IP结构体即可,不需要转换字节序,直接计算校验和。

内容的提问来源于stack exchange,提问作者S. Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:34:59