解析IP标头时出错

时间:2010-02-21 21:30:45

标签: c network-programming network-protocols

我有一个小函数,试图打印IP头的片段偏移量。

ParseIpHeader(unsigned char *packet, int len)
{
    struct ethhdr *ethernet_header;
    struct iphdr *ip_header;

    /* First Check if the packet contains an IP header using
       the Ethernet header                                */

    ethernet_header = (struct ethhdr *)packet;

    if(ntohs(ethernet_header->h_proto) == ETH_P_IP)
    {
            /* The IP header is after the Ethernet header  */

            if(len >= (sizeof(struct ethhdr) + sizeof(struct iphdr)))
            {
                    ip_header = (struct iphdr*)(packet + sizeof(struct ethhdr));

                    /* print the Source and Destination IP address */

                    //printf("Dest IP address: %s\n", inet_ntoa(ip_header->daddr));
                    //printf("Source IP address: %s\n", inet_ntoa(ip_header->saddr));
                    printf("protocol %d\n", ip_header->protocol);
                    printf("Fragment off is %d\n", ntohs(ip_header->frag_off));

            }

}

我的数据包是TCP(ip_header->协议始终是6.问题是frag_off 总是16384.我发送了大量数据,为什么frag_off总是不变?

感谢。

1 个答案:

答案 0 :(得分:3)

片段偏移与标志共享。你有“DF”(不要分段)位集。

如果片段偏移为0,则为整个16位字段提供16384。

从第10页开始,查看http://www.ietf.org/rfc/rfc791.txt

修改

您正在接收的TCP段中的DF位由远程端设置,以执行Path MTU discovery - 简而言之,尝试避免碎片。 在这种情况下,发送方学习整个路径可以处理的最大MTU,并切断TCP段,使得它们在封装到IP之后不超过它。

<强> EDIT2

关于recvfrom()和TCP的使用:TCP是面向连接的协议,并且所有分段/碎片细节都已经由它处理(碎片明显由下层IP处理) - 所以你做不需要处理它。你在发送方写的任何东西()最终都会在另一方面读取() - 可能在同一块中 - 即两次4K写入有时会导致单个8K读取,有时候两次4K读取 - 取决于媒体之间关于重新排序/丢失的行为。

IP碎片和重组由操作系统透明地处理,因此您不必担心它,与无序数据包相同等等(您将看到性能下降对应用程序的影响)

我可以推荐一个很好的读物:UNIX network programming。鉴于史蒂文参与TCP,无论您使用哪种操作系统,它都是一本好书。

<强> EDIT3:

如果你做的事情是“中间人”(假设你有合理的理由:-) - 那么你可以通过查看现有技术评估即将开展的工作:{{3 (一个脚本方法,适用于pcap文件,但适用于其他东西),或chaosreader - 它模拟IP碎片整理和TCP流重组;也许只是为了你的目的重复使用它们。